home *** CD-ROM | disk | FTP | other *** search
/ Windows News 2010 Summer - Disc 1 / WN_Ete2010_CD1.iso / Onglet5 / Weezo / Weezo setup.exe / {code_appDir} / www / js / common-src.js < prev    next >
Text File  |  2010-05-19  |  70KB  |  2,079 lines

  1. var D=document, W=window;
  2. /**
  3. * General purpose functions
  4. */
  5. function dgi(o){return document.getElementById(o)}
  6.  
  7. // D.getElementsByName, use nb="all" to get array
  8. function dgn(obn,nb){
  9.     if(!D.getElementsByName(obn).length) return;
  10.     if(nb=='all') return D.getElementsByName(obn);
  11.     if(nb==undefined || isNaN(nb)) nb=0;
  12.     return D.getElementsByName(obn)[nb];
  13. }
  14. function windowStop(){if(W.stop) W.stop(); else D.execCommand("Stop");wl.asr.cancelAll()}
  15. function fas(p2,p3,p4,p5,as){fillAndSubmit(p2,p3,p4,p5,as)}
  16. function ping() {sendData('rnd='+Math.random(), '/ping.php', true);}
  17. function cfDbg(obj,add,opt){
  18.     if(this.nb==undefined) this.nb=0;
  19.     if(this.nb++>30) return
  20.     var n,elem,o='',i=-40;
  21.     if(typeof obj!='object') o=obj;
  22.     else{
  23.         if(!opt) opt={};
  24.         while(i++<0) o+='------'; o+="\n"+(obj.id?'id='+obj.id+'/':'')+"\n";
  25.         for(elem in obj) if((!opt.noOn||elem.substr(0,2)!='on') && (!opt.noEmpty||obj[elem]!=='')){
  26.             o+=i+':'+elem+' ('+typeof(obj[elem])+')='+((!opt.det && (typeof(obj[elem])=='object' || typeof(obj[elem])=='function' || elem=='innerHTML' ||elem=='outerHTML'))?'[obj]':obj[elem])+(((++i)%3==0)?"\n":'                ');
  27.         }
  28.     }
  29.     if(add===undefined||add===false) return alert(o);
  30.     o=o.toString().replace('/</g','<').replace(/\n/g,'<br>');
  31.     if(!(n=dgi("dbg"))){
  32.     
  33.         n=D.createElement('DIV');
  34.         n.id="dbg";
  35.         with(n.style){position='absolute';top='0px';left='0px';}
  36.         D.body.appendChild(n)
  37.     }
  38.     
  39.     n.innerHTML=((add>0)?n.innerHTML:'')+o;
  40. }
  41.  
  42. D.oncontextmenu=function(e){if(W.onrightclick && ((e && e.which == 3)||(W.event && (event.button==0||event.button==2)))) return onrightclick(e); else return true}
  43.  
  44. // Count associative array items
  45. function count(a){var n=0;    for(e in a) n++; return n;}
  46. // String trim
  47. String.prototype.trim = function (){return this.replace(/^\s+|\s+$/,'');};
  48.  
  49. /**
  50. * DOM Functions
  51. */
  52. function removeNode(n){if(n.parentNode) n.parentNode.removeChild(n)}
  53.  
  54. // Get actual style value
  55. function getElementStyle(elem, styleProp, keepPx) {
  56.     if(!elem) return false;
  57.     if(phpBrowser=='ie' && styleProp.indexOf('-')!=-1){
  58.         styleProp=styleProp.substr(0,styleProp.indexOf('-'))+styleProp.substr(styleProp.indexOf('-')+1,1).toUpperCase()+styleProp.substr(styleProp.indexOf('-')+2);
  59.     }
  60.     if(keepPx){
  61.         if(W.GetComputedStyle) return W.getComputedStyle(elem, "").getPropertyValue(styleProp); // Gecko
  62.         if (elem.currentStyle) return elem.currentStyle[styleProp];// Opera & IE
  63.         return '';
  64.     }
  65.     if(W.getComputedStyle) es=W.getComputedStyle(elem, "").getPropertyValue(styleProp); // Gecko
  66.     else if (elem.currentStyle)  es=elem.currentStyle[styleProp];// Opera & IE
  67.     else return '';
  68.  
  69.     if(es.substr(es.length-2)=='px') es=es.substr(0,es.length-2);
  70.     else if(es.substr(es.length-2)=='em') {    es=es.substr(0,es.length-2)*getElementStyle(elem,'font-size');}
  71.     if(keepPx===false&&es=='auto') return 0;
  72.     return es;
  73. }
  74. function actualOffsetLeft(node){
  75.     var l=0;
  76.     while(node)    {
  77.         l+=node.offsetLeft;
  78.         if(node.style && ((ov=node.style.overflow)=='scroll' || ov=='auto')) l-=(node.scrollLeft)
  79.         node=node.offsetParent;
  80.     }
  81.     return l;
  82. }
  83. function actualOffsetRight(node){return actualOffsetLeft(node)+node.offsetWidth}
  84. function actualOffsetTop(node){
  85.     var t=0;
  86.     while(node)    {
  87.         t+=node.offsetTop;
  88.         if(!(node=node.offsetParent)) break;
  89.         if(node.style && ((ov=node.style.overflow)=='scroll' || ov=='auto')) t-=(node.scrollTop)
  90.     }
  91.     return t;
  92. }
  93. function actualOffsetBottom(node){return actualOffsetTop(node)+node.offsetHeight}
  94. function actualRect(node){
  95.     var rect={x:0,y:0,w:node.offsetWidth,h:node.offsetHeight};
  96.     while(node)    {
  97.         rect.x+=node.offsetLeft;
  98.         rect.y+=node.offsetTop;
  99.         if((ov=node.style.overflow)=='scroll' || ov=='auto') {
  100.             rect.x-=(node.scrollLeft)
  101.             rect.y-=(node.scrollTop)
  102.         }
  103.         node=node.offsetParent;
  104.     }
  105.     return rect;
  106. }
  107. function setActualHeight(node, h){
  108.     if(phpBrowser=="ie") {try{node.style.height = h} catch(err){};}
  109.     else node.style.height = (h - getElementStyle(node,'padding-top') - getElementStyle(node,'border-top-width') - getElementStyle(node,'padding-bottom') - getElementStyle(node,'border-bottom-width'))+'px';
  110. }
  111. function setActualWidth(node, w){
  112.     if(phpBrowser=="ie") {try{node.style.height = h} catch(err){};}
  113.     else node.style.width = (w - getElementStyle(node,'padding-left') - getElementStyle(node,'padding-right'))+'px';
  114. }
  115. function isParent(pn,cn){
  116.     var n=cn; var i=10;
  117.     while(--i&&(n=n.parentNode)) if(n==pn) return 1;
  118.     return 0;
  119. }
  120. function alignBottom(child, parent, margin){
  121.     var h;
  122.     if(!child || !parent) return;
  123.     if(!margin)margin=0;
  124.     if(W.winMe && parent==winMe) h=winMe.getInnerHeight();
  125.     else h=actualOffsetBottom(parent)-getElementStyle(parent,'padding-bottom',false);
  126.     h+=-actualOffsetTop(child)-getElementStyle(child,'margin-bottom',false)-margin;
  127.     setActualHeight(child,h);
  128.     return h;
  129. }
  130. // Connect listener to object. args: node, event (without "on"), callback
  131. function connect() {
  132.     var a = arguments;
  133.     return D.addEventListener?a[0].addEventListener(a[1],a[2],a[3] || false):a[0].attachEvent?a[0].attachEvent('on' + a[1], a[2]): false;
  134. }
  135. function disconnect() {
  136.     var a = arguments;
  137.     return D.removeEventListener?a[0].removeEventListener(a[1],a[2],a[3] || false):a[0].detachEvent?a[0].detachEvent('on' + a[1], a[2]): false;
  138. }
  139.  
  140. if(!W.stopPropagation) stopPropagation = function (e){e.cancelBubble=true;}
  141.  
  142.  
  143. /**
  144. * Hover
  145. */
  146. var currentHover=0;
  147. function eHover(e){
  148.     if(!e) {if(currentHover) eHoverO(currentHover); currentHover=0; return}
  149.     var targ=e.target||e.srcElement;
  150.  
  151.     var limit=10;
  152.     while(--limit>0 && targ && (!targ.getAttribute || !targ.getAttribute('eH'))) targ=targ.parentNode;
  153.     //alert(dbgObj(targ))
  154.     if(limit && targ){
  155.         if(!targ.id) targ.id="H"+Math.random();// Create id if element doesn't have one
  156.         if(targ.id && currentHover!=targ.id) eHoverI(targ.id);
  157.         if(currentHover && currentHover!=targ.id) {eHoverO(currentHover); currentHover=0;}
  158.         currentHover=targ.id;
  159.     }
  160.     else if(currentHover) {eHoverO(currentHover); currentHover=0;}
  161. }
  162. function eHoverI(objectid, classToSet){
  163.     if((W.dragInProgress && dragInProgress) || !(obJ=dgi(objectid))) return;
  164.     var cClass=obJ.className; var rClass='';
  165.     if((spP=cClass.indexOf(' '))!=-1) {rClass=cClass.substr(spP);cClass=cClass.substr(0,spP);}
  166.     if(classToSet) return obJ.className=classToSet+rClass;
  167.     if(cClass.length<5 || cClass.substr(cClass.length-5,5)!='Hover') obJ.className=cClass + 'Hover'+rClass;
  168. }
  169. function eHoverO(objectid, classToSet){
  170.     if(!(obJ=dgi(objectid)) || (W.dragInProgress && dragInProgress)) return;
  171.     var cClass=dgi(objectid).className; var rClass='';
  172.     if((spP=cClass.indexOf(' '))!=-1) {rClass=cClass.substr(spP);cClass=cClass.substr(0,spP);}
  173.     if(classToSet) return dgi(objectid).className=classToSet+rClass;
  174.     if(cClass.substr(cClass.length-5,5)=='Hover') dgi(objectid).className=cClass.substr(0,cClass.length-5)+rClass;
  175. }
  176. // Change an image or IE6 png span SRC
  177. function changeImgSrc(id,imgUrl){
  178.     if(dgi(id).tagName.toLowerCase()=='img') dgi(id).src=imgUrl;
  179.     else {
  180.         var filter=dgi(id).style.filter;
  181.         var s=filter.indexOf("src='")+5;
  182.         var e=filter.indexOf("'",s);
  183.         dgi(id).style.filter=filter.substr(0,s) + imgUrl + filter.substr(e);
  184.     }
  185. }
  186.  
  187. /**
  188. * Collapse TD
  189. * @param id: id of folded / unfolded TD
  190. */
  191. function toggleTD(id){
  192.     var cTD=dgi(id)/* folded / unfolded TD /*/, cTDS=cTD.style, ctrl=dgi(id+'_colTD') /* handle TD */,isFolded=(cTDS.display=='none'),extraParameters={},cTDDiv1S,cTDDiv2,cTDDiv2S,baseWidth;
  193.  
  194.     ctrl.lastChild.className=isFolded?'colTDUF':'colTDF';
  195.     ctrl.title=isFolded?hideCaption:showCaption;
  196.  
  197.     // Toggle server-side state
  198.     sendData("toggleTD=1&"+id+"="+(isFolded?1:0),PHP_SELF,0);
  199.  
  200.     // Add a double div wrapper into collapsed TD so width can be properly set
  201.     if(cTD.firstChild.id!==id+'_colTDD1'){
  202.         cTD.innerHTML='<div id="'+id+'_colTDD1" style="overflow:hidden;position:relative"><div id="'+id+'_colTDD2">'+cTD.innerHTML+'</div></div>';
  203.     }
  204.     cTDDiv1S=dgi(id+'_colTDD1').style;
  205.     cTDDiv2=dgi(id+'_colTDD2');    cTDDiv2S=cTDDiv2.style;
  206.  
  207.     // Unfolding
  208.     if(isFolded){
  209.         // Compute unfolded width
  210.         cTDS.width=cTDDiv1S.width='1px';
  211.         cTDDiv2S.position='absolute'
  212.         //cTDDiv2S.visibility='hidden';
  213.         cTDS.display=isFolded?'':'none';
  214.         baseWidth=cTDDiv2.offsetWidth;
  215.         cTDDiv2S.position='';
  216.  
  217.         wl.anim({'item':cTD,
  218.                 'duration':500,
  219.                 'extraParameters':{'baseWidth':baseWidth},
  220.                 'callbackComplete':function(){if(W.winResized) winResized();if(W.dd) dd.recalc()},
  221.                 'function':function(p,anim){
  222.                     p=Math.max(1,(anim.extraParameters.baseWidth*wl.animFunctionUnfold1(p)))+'px';
  223.                     cTDDiv1S.width=p;
  224.  
  225.                     return {'width':p}
  226.                 }
  227.         });
  228.     }
  229.     // Folding
  230.     else{
  231.         baseWidth=cTD.offsetWidth
  232.         extraParameters.startW=cTD.offsetWidth;
  233.         cTDDiv1S.width=baseWidth+'px';
  234.  
  235.         wl.anim({'item':cTD,
  236.                 'duration':500,
  237.                 'extraParameters':{'baseWidth':baseWidth},
  238.                 'callbackComplete':function(){
  239.                     cTDS.display='none';
  240.                     if(W.winResized) winResized();if(W.dd) dd.recalc()
  241.                 },
  242.                 'function':function(p,anim){
  243.                     p=Math.max(1,(anim.extraParameters.baseWidth*wl.animFunctionFold1(p)))+'px';
  244.                     cTDDiv1S.width=p;
  245.                     return {'width':p}
  246.                 }
  247.         });
  248.     }
  249.  
  250.     if(W.winResized) winResized();
  251. }
  252. function toggleTDHL(n){
  253.     var id=n.id;
  254.     if(!id) return;
  255.     id=id.substr(0,id.length-6);
  256.     if(dgi(id).style.display=='none') {
  257.         if(!dd.obj || dd.obj.id!=='dragMaskDiv') toggleTD(id);
  258.     }
  259. }
  260.  
  261.  
  262.  
  263.  
  264. /**
  265. * Fade in-out (0 <= alpha <= 1)
  266. * i: item or id of item
  267. * aSt: alpha start
  268. * aEn: alpha target
  269. * nbSteps: nb of steps
  270. * cb: js callback on completition (eval'ed)
  271. * stepCb: js callback on each step (eval'ed)
  272. */
  273. function fade(i, aSt, aEn, nbSteps, cb, stepCb, aCur){
  274.     if(typeof(i)=='object'){if(i.id) i=i.id; else i=i.id='id'+Math.floor(999999*Math.random());}
  275.     if(wl.fadeItems[i] && wl.fadeItems[i]!=aEn) return; // Another fadeto has set a new target alpha
  276.     
  277.     var ini,finished=0,n=dgi(i),s=n.style;
  278.     
  279.     // Simple onload fade: use new animation function
  280.     if(aSt===undefined){
  281.         if($(n).e.getStyle('visibility')!=='visible') s.visibility='visible';
  282.         if($(n).e.getStyle('display')=='none') s.display='inline';
  283.         wl.anim({'item':n,'duration':500,'function':function(p,a){
  284.             return {'opacity':p}}
  285.         });
  286.         return;
  287.     }
  288.     
  289.     if(aSt==undefined) {aSt=0;aEn=1}
  290.     if(aEn==undefined) aEn=aSt;
  291.     if(nbSteps==undefined) {
  292.         if(aSt==aEn) nbSteps=1; else nbSteps=imgFadeSteps;
  293.     }
  294.     
  295.     if(aCur==undefined) {aCur=aSt;ini=1;}
  296.     aCur+=(aEn-aSt)/nbSteps;
  297.  
  298.     if(!n) return;
  299.  
  300.     if(aEn  > aSt && aCur >= aEn){finished=1;aCur=aEn;}
  301.     if(aEn <= aSt && aCur <= aEn){finished=1;aCur=aEn;}
  302.     setAlpha(n,aCur);
  303.  
  304.     if(aCur>0 && ini && (s.display=="none" || s.visibility!="visible")) {s.display=""; s.visibility="visible"}
  305.     if(aCur==0) s.display="none";
  306.  
  307.     if(!finished) W.setTimeout('fade("'+ i +'", '+aSt+', '+aEn+', '+nbSteps+', \''+cb+'\', \''+stepCb+'\', '+aCur+')',5);
  308.     else{
  309.         if(cb!==undefined && cb!==false) eval(cb);
  310.         if(wl.fadeItems[i]!==undefined) delete(wl.fadeItems[i]);
  311.     }
  312.     if(stepCb) eval(stepCb);
  313. }
  314.  
  315. // Set opacity (0<=alpha<=1)
  316. function setAlpha(n,alpha){
  317.     with(n.style){
  318.         if(alpha==1) {
  319.             var s
  320.             if((s=n.getAttribute('style')) && s.removeAttribute) s.removeAttribute('filter')
  321.             opacity='';
  322.         }
  323.         else {
  324.             filter="Alpha(opacity="+(Math.round(100*alpha))+")";
  325.             opacity=Math.round(100*alpha)/100;
  326.         }
  327.     }
  328. }
  329. /**
  330. * Fold/unfold
  331. */
  332. function fold(itemId,onFoldedFunction){
  333.     var item=dgi(itemId);
  334.     if(item.style.overflow!='hidden') item.style.overflow='hidden';
  335.     var h=item.offsetHeight;
  336.  
  337.     if(h<11){
  338.         item.style.height='0';
  339.         if(onFoldedFunction) eval(onFoldedFunction+'("'+itemId+'")');
  340.     }
  341.     else{
  342.         item.style.height=(h*0.6)+'px';
  343.         W.setTimeout('fold("'+itemId+'"'+((onFoldedFunction)?',"'+onFoldedFunction+'")':')'),1);
  344.     }
  345. }
  346. function unfold(itemId,unfoldedHeight,onUnFoldedFunction){
  347.     var item=dgi(itemId);
  348.     if(item.style.overflow!='hidden') item.style.overflow='hidden';
  349.     var h=Math.max(item.offsetHeight,10)*1.4;
  350.  
  351.     if(h>=unfoldedHeight){
  352.         item.style.unfoldedHeight=h+'px';
  353.     }
  354.     else{
  355.         item.style.height=h+'px';
  356.         W.setTimeout('unfold("'+itemId+'",'+unfoldedHeight+((onUnFoldedFunction)?',"'+onUnFoldedFunction+'")':')'),1);
  357.     }
  358. }
  359.  
  360.  
  361. /**
  362. * Buttons (bt)
  363. */
  364. function btEnable(id){
  365.     dgi(id).getElementsByTagName('a')[0].className="up";
  366.     if(dgi(id).getElementsByTagName('legend')[0].innerHTML) dgi(id).getElementsByTagName('a')[0].href=dgi(id).getElementsByTagName('legend')[0].innerHTML;
  367. }
  368. function btDisable(id){
  369.     dgi(id).getElementsByTagName('a')[0].className="off";
  370.     if(dgi(id).getElementsByTagName('a')[0].href!="javascript:;") dgi(id).getElementsByTagName('legend')[0].innerHTML=dgi(id).getElementsByTagName('a')[0].href;
  371.     dgi(id).getElementsByTagName('a')[0].href="javascript:;";
  372. }
  373. function btActivate(id){
  374.     if(dgi(id).getElementsByTagName('a')[0].className=="off"){
  375.         if(dgi(id).getElementsByTagName('legend')[0].innerHTML) dgi(id).getElementsByTagName('a')[0].href=dgi(id).getElementsByTagName('legend')[0].innerHTML;
  376.     }
  377.     dgi(id).getElementsByTagName('a')[0].className="on";
  378. }
  379. function btState(id){return dgi(id).getElementsByTagName('a')[0].className;}
  380. function btSetCaption(id,t){
  381.     dgi(id).getElementsByTagName('q')[0].innerHTML=t;
  382.     if(phpBrowser=='ie') dgi(id).getElementsByTagName('s')[0].innerHTML=t;
  383.     btAdjustText(id);
  384. }
  385. function btSetIcon(id,s){
  386.     dgi(id).getElementsByTagName('IMG')[0].src=s;
  387.     btAdjustText(id);
  388. }
  389. function btAdjustText(id){
  390.     if(phpBrowser=='ie') return;
  391.     var txt=dgi(id).getElementsByTagName('s')[0].innerHTML;
  392.     if(dgi(id).getElementsByTagName('q')[0].innerHTML.length) txt=dgi(id).getElementsByTagName('q')[0].innerHTML;
  393.     else dgi(id).getElementsByTagName('q')[0].innerHTML=txt;
  394.  
  395.     dgi(id).getElementsByTagName('s')[0].innerHTML=txt;
  396.  
  397.     var txtArea=dgi(id).getElementsByTagName('s')[0];
  398.     var buttonArea=dgi(id).getElementsByTagName('u')[0];
  399.  
  400.     var dots='...';
  401.     if(!dgi(id).title) dgi(id).title=txt;
  402.     while(txtArea.offsetLeft+txtArea.offsetWidth>buttonArea.offsetLeft){
  403.         txt=txt.substr(0,txt.length-1);
  404.         txtArea.innerHTML=txt+dots;
  405.         if(!txt.length) {
  406.             if(dots.length) dots=dots.substr(0,dots.length-1);
  407.             else  {
  408.                 txtArea.innerHTML=' ';
  409.                 break;
  410.             }
  411.         }
  412.     }
  413. }
  414. function btSetWidth(id, newWidth){
  415.     if(!dgi(id)) return;
  416.     dgi(id).getElementsByTagName('DIV')[0].style.width=newWidth
  417. }
  418.  
  419.  
  420. /**
  421. * Progress bar
  422. */
  423. function progressSetText(id,txt){dgi(id+'_text').innerHTML=txt;}
  424. function progressGetText(id){return dgi(id+'_text').innerHTML}
  425. function progressSetPerc(id,perc){dgi(id+'_inner').style.width=Math.floor(perc)+'%'}
  426. function progressGetPerc(id){var p=dgi(id+'_inner').style.width;return p.substr(0,p.length-1)}
  427.  
  428. /**
  429. * Tooltip
  430. */
  431. var tooltipDx=10;
  432. var tooltipDy=10;
  433. var tooltipDelay=500;     // Delay before displaying tooltip (ms)
  434. var tooltipNodeId=0;    // Node id of currently displayed or to-be-displayed tooltip
  435. var tooltipShown=0;     // 1 if tooltip is displayed
  436. var tooltipContentFunction; // cache for tooltip text content function
  437.  
  438.  
  439. /**
  440. * CONTEXT MENU
  441. */
  442. var contextMenuDOC,contextMenuTime,contextMenuObject;
  443. function ContextMenuKD(e){
  444.     if(wl.eventKC(e)==27) contextMenuObject.remove();
  445.     if(wl.eventKC(e)==13) {
  446.         var it=contextMenuObject.items;
  447.         for (i=0;i<it.length;i++) if(it[i]['def']) {contextMenuObject.remove();eval(it[i]['action']);return;}
  448.     }
  449. }
  450. function ContextMenuItem(ico,caption,action,def){if(ico==='sep') return ico; return {'icon':ico,'caption':caption,'action':action,'def':def}}
  451.  
  452. /* Context menu item
  453.  * items: array of context menu items
  454.  * opts: assoc array of options :
  455.      button=>node to attach as drop-down menu
  456.      align=>'right' or 'left':drop-down menu alignement
  457.  */
  458. function ContextMenu(items,opt){
  459.     this.remove=function(e){
  460.         if(wl.chrono.microtime()-contextMenuTime<100) return;
  461.         disconnect(D,'keydown',ContextMenuKD)
  462.         maskHide();
  463.         if(dgi('contextMenu')) removeNode(dgi('contextMenu'))
  464.         if(contextMenuDOC) D.onclick=contextMenuDOC;
  465.     }
  466.     if(!items) return;
  467.     var x=W.mouseX,y=W.mouseY;
  468.     if(x==undefined && !opt['button']) return;
  469.  
  470.     this.items=items;
  471.  
  472.     if(!opt) opt={};
  473.     var cm=D.createElement('DIV');
  474.     cm.id='contextMenu';
  475.     cm.className='dropShadow';
  476.  
  477.     with(cm.style){visibility='hidden';top=0;left=0;}
  478.  
  479.  
  480.     var o='',it,e;
  481.     //o='<table cellpadding=0 cellspacing=0><tr><td>';
  482.     o+='<div class="contextMenu" id="contextMenuDiv">';
  483.     for(var i=0;i<items.length;i++){
  484.         if((it=items[i])=='sep') {
  485.             if(i+1<items.length && i>0 && items[i-1]!='sep') o+='<div class="sep"></div>';
  486.         }
  487.         else if(it['action']){
  488.             o+='<a href="javascript:(new ContextMenu()).remove();'+it['action']+'"'+((it['def'])?' style="font-weight:bold"':'')+'>';
  489.             o+='<img src="'+(it['icon']||'/gfx/v.gif')+'">'+it['caption']+'</a>';
  490.         }
  491.         else{
  492.             o+='<div class="disabled"><img src="'+(it['icon']||'/gfx/v.gif')+'">'+it['caption']+'</div>';
  493.         }
  494.     }
  495.     o+='</div>';
  496.     //o+='</td><td class="sIEr"> </td></tr><tr class="sIEtrb"><td class="sIEb"></td><td class="sIErb"></td></tr></table>';
  497.     cm.innerHTML=o;
  498.     contextMenuTime=wl.chrono.microtime()
  499.     maskShow(true,false,false,this.remove)
  500.  
  501.     D.body.appendChild(cm);
  502.  
  503.     // Extra style
  504.     if(opt.style) for(e in opt.style) cm.style[e]=opt['style'][e];
  505.     // Set menu position
  506.     with(cm.style){
  507.         zIndex=maskNode().style.zIndex+1;
  508.         if(opt['button']){
  509.             y=actualOffsetBottom(opt['button']);
  510.             if(opt['align']=='right')
  511.                 x=actualOffsetRight(opt['button'])-cm.offsetWidth;
  512.             else
  513.                 x=actualOffsetLeft(opt['button']);
  514.  
  515.         }
  516.         else{
  517.             if(opt['centerFirst']) {x-=12;y-=dgi("contextMenuDiv").firstChild.offsetHeight/2}
  518.             x=Math.min(x,dd.getWndW()-cm.offsetWidth)
  519.             y=Math.min(y,dd.getWndH()-cm.offsetHeight-20);
  520.         }
  521.         left=x;top=y;
  522.     }
  523.  
  524.     // Egalize all items widths in IE
  525.     if(phpBrowser=='ie'){
  526.         var sn=cm.firstChild.childNodes,mw=0,e;
  527.         for(e in sn) mw=Math.max(mw,sn[e].offsetWidth||0);
  528.         if(opt.style && opt.style.width) mw=opt.style.width;
  529.         for(e in sn) if(sn[e].nodeType==1) sn[e].style.width=mw+'px';
  530.         cm.style.visibility='visible';// IE8 WA
  531.     }
  532.     if(opt['fade']) fade(cm); else cm.style.visibility='';
  533.  
  534.     connect(D,'keydown',ContextMenuKD,false);
  535.     contextMenuObject=this;
  536. }
  537. // Attach a context menu to a given node
  538. function ContextMenuAttach(n,items,opt){
  539.     if(typeof(n)=='string') n=dgi(n); if(!n) return;
  540.     if(!opt) opt={}; if(opt['button'] && (typeof opt.button)!='object') opt['button']=n;
  541.     n.oncontextmenu=function(event){var cm=new ContextMenu(items,opt);return false}
  542.     if(opt['leftClick']) n.onclick=function(event){var cm=new ContextMenu(items,opt);return false}
  543. }
  544. // Attach a context menu to a given node
  545. // node: node to attach menu
  546. // items: array of ContextMenuItem
  547. // opt: options (style: assoc array of style properties, button: 1 to attach as button drop-down list to node or otherNode to attach to another DOM node, leftClick to trigger on left click)
  548. function ContextMenuDropDown(node,items,opt){
  549.     if(typeof(node)=='string') node=dgi(node); if(!node) return;
  550.     if(!opt) opt={};opt['button']=node;
  551.     if(!opt['align']) opt['align']='left';
  552.     node.onclick=function(event){var cm=new ContextMenu(items,opt);return false}
  553. }
  554.  
  555. // Attach a context menu to a given node
  556. function ContextMenuDetach(node){
  557.     if(typeof(node)=='string') node=dgi(node); if(!node) return;
  558.     node.oncontextmenu='';
  559. }
  560.  
  561. /**
  562. * @desc Mouseover function: entry-point for tooltip
  563. *         start timer to dispay tooltip
  564. * @param DOMnode node
  565. * @param string txtContent (optional): content of tooltip. If not set, content is set from tooltipGetContent function
  566. * @param bool noDelay: true to display immediately
  567. */
  568. var tooltipOnMouseDownFunction,tooltipOnMouseOutFunction; // Temp storage of onmouseout and onmousedown functions, converted to text
  569. function tooltip(node, txtContent, noDelay){
  570.     if(!node || (!txtContent && !W.tooltipGetContent) || (W.winMe && !winMe.isActive())) return; // Wrong parameters / config
  571.     
  572.     //if(typeof node="string" && dgi(node)) node=dgi(node); // If passed var is node id instead of id
  573.     if(!node.id) node.id='tooltip'+Math.floor(Math.random()*100000);
  574.     if(tooltipNodeId==node.id) return; // Wrong parameters / config
  575.  
  576.     // If a tooltip is currently shown, destroy it first (should rarely happend)
  577.     //if(tooltipShown) tooltipHide(tooltipNodeId,onmouseoutFunction,'out')
  578.     
  579.     tooltipNodeId=node.id;
  580.     tooltipShown=0;
  581.  
  582.     // Memorize onmouseout function (converted to string)
  583.     if(node.onmouseout)    {
  584.         var omo=' '+node.getAttribute('onmouseout'); omo=omo.substr(1);
  585.         // IE
  586.         if(omo.indexOf('function anonymous')!=-1){omo=omo.substr(23,omo.length-24)}
  587.         
  588.         if(omo.indexOf('tooltipHide')==-1) tooltipOnMouseOutFunction=omo;
  589.     }
  590.     node.onmouseout=function(e){tooltipHide(node.id,'out')};
  591.  
  592.     // Memorize onmousedown function (converted to string)
  593.     if(node.onmousedown)    {
  594.         var omd=' '+node.getAttribute('onmousedown'); omd=omd.substr(1);
  595.         // IE
  596.         if(omd.indexOf('function anonymous')!=-1){omd=omd.substr(23,omd.length-24)}
  597.         
  598.         if(omd.indexOf('tooltipHide')==-1) tooltipOnMouseDownFunction=omd;
  599.     }
  600.     
  601.     node.onmousedown=function(e){tooltipHide(node.id,'down')}
  602.  
  603.     // Delay-call tooltip show function
  604.     tooltipContentFunction=null;
  605.     if(!txtContent) txtContent='';
  606.     if((typeof txtContent)!='string') {tooltipContentFunction=txtContent; txtContent=''}
  607.     W.setTimeout('tooltipShow("'+node.id+'","'+txtContent.replace(/"/g,'\\"')+'",1)',((noDelay)?0:tooltipDelay)); /* \\"*/
  608. }
  609.  
  610. // Show tooltip
  611. function tooltipShow(nodeId,txtContent,calledByTimer){
  612.     var tooltipDiv,node=dgi(nodeId),content;
  613.     if(!node || (tooltipNodeId!=nodeId && calledByTimer) || tooltipShown) return; // Error or other tooltip requested since, or tooltip already shown
  614.  
  615.     // Get tooltip content
  616.     content=txtContent?txtContent:(tooltipContentFunction)?tooltipContentFunction(node):W.tooltipGetContent(node.id);
  617.  
  618.     // No tooltip content: tooltip should not be displayed
  619.     if(!content) {
  620.         if(calledByTimer && node.onmouseout!=null) node.onmouseout();
  621.         return;
  622.     }
  623.     // Remove previous tooltip if existing
  624.     tooltipDestroy();
  625.  
  626.     // Create container that will host tooltip node
  627.     if(!dgi('dragDetach')) {
  628.         var ddNode=D.createElement("div");
  629.         ddNode.id="dragDetach";
  630.         with(ddNode.style){position="absolute";top=0;left=0;zIndex=10000};
  631.         D.body.appendChild(ddNode);
  632.     }
  633.  
  634.     // Create tooltip DOM node
  635.     tooltipDiv=D.createElement("div");
  636.     tooltipDiv.id='tooltip';
  637.     tooltipDiv.className='tooltip';
  638.     tooltipDiv.style.display='none';
  639.     tooltipDiv.style.width='400px';
  640.  
  641.     // Fill content
  642.     tooltipDiv.innerHTML=content;
  643.     dgi('dragDetach').appendChild(tooltipDiv)
  644.  
  645.     // Set draggable
  646.     ADD_DHTML('tooltip',1);
  647.     dd.elements['tooltip'].maximizeZ();
  648.  
  649.     // Set onmousemove function
  650.     node.onmousemove=function(event){tooltipMove(nodeId)};
  651.  
  652.     tooltipShown=1;
  653.     dgi('tooltip').style.display='block';
  654.     tooltipAdjustToContent();
  655.     tooltipMove(nodeId);
  656. }
  657. function tooltipSetContent(h){
  658.     if(!dgi('tooltip')) return;
  659.     with(dgi('tooltip').style) {visibility='hidden';top=0;left=0}
  660.     dgi('tooltip').innerHTML=h;
  661.     tooltipAdjustToContent();
  662.     tooltipMove();
  663. }
  664. function tooltipAdjustToContent(){
  665.     dgi('tooltip').style.width='auto'
  666.     dgi('tooltip').style.height=''
  667. }
  668. function tooltipMove(nodeId){
  669.     if(!nodeId) nodeId=tooltipNodeId;
  670.     if(nodeId!=tooltipNodeId || !tooltipShown || !dgi('tooltip')) return;
  671.     var offsetX=(W.pageXOffset?W.pageXOffset:D.body.scrollLeft);
  672.     var offsetY=(W.pageYOffset?W.pageYOffset:D.body.scrollTop);
  673.     var ttx=mouseX+tooltipDx,tty=mouseY+tooltipDy,tt=dgi('tooltip');
  674.  
  675.     if(tty+tt.offsetHeight>offsetY+D.body.clientHeight) tty=offsetY+D.body.clientHeight-10-tt.offsetHeight;
  676.     if(ttx+tt.offsetWidth>offsetX+D.body.clientWidth){
  677.         if(tt.offsetWidth > D.body.clientWidth) {
  678.             tt.style.whiteSpace='normal';
  679.             tt.style.width=(Math.floor(0.9*D.body.clientWidth))+'px';
  680.             ttx=(Math.floor(0.05*D.body.clientWidth))+'px';
  681.         }
  682.         else ttx=mouseX - tooltipDx - tt.offsetWidth;
  683.     }
  684.     dd.elements['tooltip'].moveTo(Math.max(5,ttx),tty);
  685. }
  686. function tooltipHide(nodeId,mouseXXX){
  687.     var node;
  688.  
  689.     if(nodeId==tooltipNodeId) tooltipNodeId=0;
  690.     tooltipShown=0;
  691.  
  692.     tooltipDestroy();
  693.  
  694.     if(!(node=dgi(nodeId))) return;
  695.  
  696.     // Restore onmouseout function
  697.     if(mouseXXX=='out' && tooltipOnMouseOutFunction) eval(tooltipOnMouseOutFunction.replace(/this/g,'dgi(nodeId)'));
  698.     if(mouseXXX=='down' && tooltipOnMouseDownFunction)    eval(tooltipOnMouseDownFunction.replace(/this/g,'dgi(nodeId)'));
  699.     if(tooltipOnMouseOutFunction) node.onmouseout=tooltipOnMouseOutFunction;
  700.     if(tooltipOnMouseDownFunction) node.onmousedown=tooltipOnMouseDownFunction;
  701.     tooltipOnMouseDownFunction=0;
  702.     tooltipOnMouseOutFunction=0;
  703.     node.onmousemove=null;
  704. }
  705. /**
  706. * @desc Remove tooltip DOM node and DHTML element
  707. */
  708. function tooltipDestroy(){
  709.     if(dd.elements['tooltip']) {
  710.         dd.elements['tooltip'].hide();
  711.         dd.elements['tooltip'].del(1);
  712.     }
  713.     if(dgi('tooltip')) dgi('tooltip').parentNode.removeChild(dgi('tooltip'));
  714. }
  715. /**
  716. * @desc Fill tooltip with dedicated associative array
  717. */
  718. function tooltipSetProperties(p){
  719.     function tooltipCleanCode(arr){
  720.         for(elem in arr) {
  721.             if(typeof(arr[elem])=='string'){
  722.                 if(arr[elem].substr(0,5)=='code:') arr[elem]=arr[elem].substr(5);
  723.             }
  724.             else tooltipCleanCode(arr[elem]);
  725.         }
  726.     }
  727.     if(!dgi('tooltip')) return;
  728.  
  729.     //tooltipCleanCode(p)
  730.  
  731.     var content='';
  732.     // Header
  733.     content='<div class="tooltipHeader">'+((p['icon'])?'<img src="'+p['icon']+'" alt="" style="vertical-align:middle;margin-right:0.5em">':'')+((p['header'])?((p['header']['c'])?p['header']['c']:p['header']):p['filename'])+'</div>'
  734.     var tURL='';
  735.     for(elem in p) if(elem=='thumbnailURL') {tURL=p[elem];break}
  736.  
  737.     // Table for thumbnail + extra data
  738.     if(tURL && p['extra']) content+='<table><tr style="vertical-align:top"><td style="padding-right:1em">';
  739.  
  740.     // Thumbnail
  741.     if(tURL) {
  742.  
  743.         // If no extra data, center image
  744.         if(!p['extra'] && tURL.substr(0,5)!='code:') content+='<center>';
  745.  
  746.         // Image border frame
  747.         content+='<div class="tooltipImage"'+((p['thumbnailNoFrame'])?' style="border:0;padding:0;background:transparent"':'')+'>';
  748.         // HTML code
  749.         if(tURL.substr(0,5)=='code:'){
  750.             content+=tURL.substr(5);
  751.         }
  752.         // URL
  753.         else{
  754.             content+='<img src="'+loadingIconURL+'" style="position:absolute;margin-left:'+(Math.floor(p['thumbnailURLW']/2)-8)+'px;margin-top:'+(Math.floor(p['thumbnailURLH']/2)-8)+'px">';
  755.             content+='<img id="tooltipImg" style="visibility:hidden" alt="" src="'+tURL+'" onload="tooltipImgLoaded()" width="'+p['thumbnailURLW']+'" height="'+p['thumbnailURLH']+'">';
  756.         }
  757.         content+='</div>';
  758.  
  759.         if(!p['extra'] && tURL.substr(0,5)!='code:') content+='</center>';
  760.     }
  761.  
  762.     if(tURL && p['extra']) content+='</td><td>';
  763.  
  764.     // Extra content (right part of thumbnail)
  765.     if(p['extra']){
  766.         if(p['extra']['extraTitle']){
  767.             content+='<b>'+p['extra']['extraTitle']['c']+'</b><br/>';
  768.             delete(p['extra']['extraTitle']);
  769.         }
  770.         content+='<table style="font:inherit;vertical-align:top">';
  771.         var nb=0;for(elem in p['extra']) nb++;
  772.         var elemNb=0;
  773.         for(elem in p['extra']){
  774.             if(nb<24 || elemNb%2==0) content+='<tr><td style="padding-right:1em">';
  775.             else content+='<td style="padding-right:1em;padding-left:3em">';
  776.  
  777.             if(p['extra'][elem]['v'])
  778.             content+='<b>'+p['extra'][elem]['c']+'</b></td><td>'+p['extra'][elem]['v']+'</td>';
  779.             else if(p['extra'][elem]['c']) content+='</td><td>'+p['extra'][elem]['c']+'</td>';
  780.             else content+='<b>'+elem+'</b></td><td>'+p['extra'][elem]+'</td>';
  781.  
  782.             if(nb<24 || elemNb%2==1) content+='</tr>';
  783.             elemNb++;
  784.         }
  785.         if(nb>23 && elemNb%2==0) content+='</tr>';
  786.         content+='</table>';
  787.     }
  788.  
  789.     if(tURL && p['extra']) content+='</td></tr></table>';
  790.  
  791.     // Footer
  792.     if(p['footer']){
  793.         content+='<div class="tooltipFooter">';
  794.         if(p['footer']['c']) content+='<b>'+p['footer']['c']+'</b>'+p['footer']['v']; else content+=p['footer'];
  795.         p['footer']+='</div>';
  796.     }
  797.     else if(p['cTime'] && p['mTime']){
  798.         content+='<div class="tooltipFooter">';
  799.         content+='<div style="width:30em;display:block;height:1px;overflow:hidden"></div>';
  800.         content+='<div style="position:absolute;right:1em"><b>'+p['fileSize']['c']+p['sep']+'</b>'+p['fileSize']['v']+'</div>';
  801.         content+='<div><b>'+p['cTime']['c']+p['sep']+'</b>'+p['cTime']['v']+'</div>';
  802.         content+='<div><b>'+p['mTime']['c']+p['sep']+'</b>'+p['mTime']['v']+'</div>';
  803.         content+='</div>';
  804.     }
  805.  
  806.     // Set content and fade-in
  807.     tooltipSetContent(content);
  808.     fade('tooltip',0,1,3);
  809. }
  810. // Thumbnail image loaded
  811. function tooltipImgLoaded(){
  812.     if(!dgi("tooltipImg")) return;
  813.     if(dgi("tooltipImg").previousSibling) dgi("tooltipImg").parentNode.removeChild(dgi("tooltipImg").previousSibling);
  814.     tooltipAdjustToContent();
  815.     fade("tooltipImg",0,1,5)
  816. }
  817.  
  818.  
  819. /**
  820. * MASK
  821. */
  822. var maskShown=0;
  823. function maskShow(transparent,doFadeIn,wCurs,onclickF,innerHTML){
  824.     var maskDiv, create, maskDivBg;
  825.     // Create if inexisting
  826.     if(!dgi('maskDiv')){
  827.         maskDiv=D.createElement("div");
  828.         maskDiv.id='maskDiv';
  829.         create=1;
  830.     }
  831.     // Or retreive
  832.     else maskDiv=dgi('maskDiv');
  833.     
  834.     // Set inner HTML (use maskDivBg to prevent opacity to be applied to innerHTML)
  835.     maskDiv.innerHTML='<div id="maskDivBg" style="position:absolute;height:100%;width:100%;background:black;border:1px solid red;left:0px;top:0px"> </div>'+((innerHTML)?'<div style="position:relative;top:50%;text-align:center">'+innerHTML+'</div>':'');
  836.  
  837.     // Set onclick and oncontextmenu
  838.     if(onclickF) {
  839.         maskDiv.onclick=onclickF;
  840.         maskDiv.oncontextmenu=function(event){onclickF();return maskRC(event);}
  841.     }
  842.     else maskDiv.oncontextmenu=maskRC;
  843.  
  844.     with(maskDiv.style){
  845.         // Hide
  846.         display='none';    position='absolute';
  847.         // Cursor
  848.         if(!wCurs) curor='pointer';
  849.         else if(wCurs===true) cursor='wait';
  850.         else cursor=wCurs;
  851.         // Position
  852.         top='0'; left='0'; margin='0'; padding='0';
  853.         width=D.body.scrollWidth;
  854.         height=Math.max(D.body.scrollHeight,(W.winMe)?winMe.getInnerHeight():0)-0
  855.         zIndex=Math.max(99998,(W.dd && dd.z)?dd.z*1+1:0);
  856.     }
  857.     if(create) D.body.insertBefore(maskDiv,D.body.firstChild);
  858.     
  859.     maskDivBg=dgi('maskDivBg')
  860.     // Color
  861.     maskDivBg.style.background='black';
  862.     // Opacity
  863.     setAlpha(maskDivBg,(transparent)?0.01:0.2);
  864.     
  865.     if(doFadeIn) wl.anim({'item':maskDivBg,'duration':300,'function':function(p,anim){if(p==0) dgi('maskDiv').style.display='';return {'opacity':p*0.2}}}); else maskDiv.style.display='';
  866.     //if(doFadeIn) fade(maskDiv,0,0.2,3); else maskDiv.style.display='';
  867.     maskShown=1;
  868. }
  869. function maskHide(doFadeOut){
  870.     maskShown=0;
  871.     if(!dgi('maskDiv')) return;
  872.     if(doFadeOut) fade(dgi('maskDiv'),0.2,0,3,'removeNode(dgi("maskDiv"))'); else removeNode(dgi('maskDiv'));
  873. }
  874. function maskNode(){return dgi('maskDiv')};
  875. function ffLoadWA(){D.createElement('div').innerHTML='<img src=\"/gfx/v.gif\">'}
  876. function maskRC(e){if(!e) e=event;    if(e.stopPropagation) e.stopPropagation(); else    e.cancelBubble=true;    return false;}
  877. function maskMoveAbove(n){
  878.     if(!maskNode()) return;
  879.     if(n.id && W.dd && dd.elements[n.id]) dd.elements[n.id].setZ(Math.max(dd.z,maskNode().style.zIndex*1+1))
  880.     else n.style.zIndex=maskNode().style.zIndex*1+1;
  881. }
  882.  
  883. /**
  884. * dialog box
  885. *
  886. * DialogBox object
  887. * definition: array
  888. *     title(opt): box title
  889. *     text: main text,
  890. *     icon(opt): icon src,
  891. *     buttons: array:
  892. *         'ok'(opt): caption of ok button,
  893. *         'cancel'(opt): caption of cancel button
  894. *     check(opt): bool, true if default checked, false if default not checked
  895. *     checkText(opt): string: checkbox text
  896. *
  897. callBackFunction: string: name of callback function
  898. */
  899. function dialogBox(definition,callbackFunction){
  900.     this.definition=definition;
  901.     this.callbackFunction=callbackFunction?callbackFunction:'';
  902. }
  903. dialogBox.prototype.show = function (){
  904.     if(this.definition['mask']) maskShow(false,true,false); else maskShow(true);
  905.  
  906.     var boxDiv=D.createElement("div");
  907.     boxDiv.id='dialogBox';
  908.     boxDiv.className='popup';
  909.     boxDiv.style.display='none';
  910.     boxDiv.style.width='400px';
  911.     boxDiv.style.zIndex=dgi('maskDiv').style.zIndex+1;
  912.  
  913.     iconImage='';
  914.     if(this.definition['icon']) iconImage='<img id="dialogBoxIcon" src="'+this.definition['icon']+'" style="vertical-align:middle;margin-right:0.5em">';
  915.  
  916.     // Title
  917.     iht='';
  918.     if(this.definition['title']) iht+='<div class="popupHeader" id="dialogBoxTitle">'+iconImage+this.definition['title']+'</div>';
  919.     else iht+=iconImage;
  920.  
  921.     // main caption
  922.     if(this.definition['text']) iht+='<span id="dialogBoxText">'+this.definition['text']+'</text>';
  923.  
  924.     iht+='<br><br><center>';
  925.     // text input
  926.     if(this.definition['input']!==undefined) iht+='<input type="text" class="textInput" style="width:80%" id="dialogBoxInput" value="'+this.definition['input']+'"><br>';
  927.     var nb=0; for(e in this.definition['buttons']) nb++;
  928.  
  929.     // OK button
  930.     if(this.definition['buttons']['ok']) iht+=wl.button.create(this.definition['buttons']['ok'],"dialogBoxButtonPressed('ok','"+this.callbackFunction+"')",'/gfx/ok.png','dialogBoxOK')+((nb-->0)?'   ':'');
  931.  
  932.     // Cancel button
  933.     if(this.definition['buttons']['cancel']) iht+=wl.button.create(this.definition['buttons']['cancel'],"dialogBoxButtonPressed('cancel','"+this.callbackFunction+"')",'/gfx/cancel.png','dialogBoxCancel')+((nb-->0)?'   ':'');;
  934.  
  935.  
  936.     iht+='</center>';
  937.  
  938.     if(this.definition['check']!=undefined) iht+='<input id="dialogBoxCheck" type="checkbox"'+((this.definition['check'])?' checked="checked"':'')+'> ';
  939.     if(this.definition['checkText']) iht+='<span id="dialogBoxCheckText" onclick="dgi(\'dialogBoxCheck\').checked=!dgi(\'dialogBoxCheck\').checked">'+this.definition['checkText']+'</span>';
  940.     // Fill content
  941.     boxDiv.innerHTML=iht;
  942.  
  943.     //D.body.insertBefore(boxDiv,D.body.firstChild);
  944.     D.body.appendChild(boxDiv);
  945.  
  946.     // input keystrike monitoring
  947.     if(this.definition['input']!==undefined) wl.setKeycodeListener('dialogBoxInput',this.inputKD)
  948.  
  949.     if(this.definition['fade']) fade('dialogBox'); else boxDiv.style.display='';
  950.     boxDiv.style.top=(winMe.getInnerHeight()-boxDiv.offsetHeight)/2;
  951.     boxDiv.style.left=(winMe.getInnerWidth()-boxDiv.offsetWidth)/2;
  952. }
  953. dialogBox.prototype.inputKD = function (kc){
  954.     if(kc==27 && dgi('dialogBoxCancel')) eval(dgi('dialogBoxCancel').href)
  955.     if(kc==13 && dgi('dialogBoxOK')) eval(dgi('dialogBoxOK').href)
  956. }
  957. dialogBox.prototype.hide = function (){
  958.     dgi('dialogBox').parentNode.removeChild(dgi('dialogBox'));
  959.     maskHide();
  960. }
  961. dialogBox.prototype.item=function(name){
  962.     if(name=='ok') return dgi('dialogBoxOK');
  963.     if(name=='cancel') return dgi('dialogBoxCancel');
  964.     if(name=='input') return dgi('dialogBoxInput');
  965.     if(name=='check') return dgi('dialogBoxCheck');
  966.     if(name=='title') return dgi('dialogBoxTitle');
  967.     if(name=='text') return dgi('dialogBoxText');
  968.     if(name=='checkText') return dgi('dialogBoxCheckText');
  969.     if(name=='icon') return dgi('dialogBoxIcon');
  970. }
  971. function dialogBoxButtonPressed(button,callback){
  972.     var result={'button':button};
  973.     if(dgi('dialogBoxCheck')) result['check']=dgi('dialogBoxCheck').checked;
  974.     if(dgi('dialogBoxInput')) result['input']=dgi('dialogBoxInput').value;
  975.     if((!callback) || window[callback](result)==undefined){
  976.         dgi('dialogBox').parentNode.removeChild(dgi('dialogBox'));
  977.         maskHide();
  978.     }
  979. }
  980.  
  981.  
  982.  
  983. // Async submit comForm
  984. function asyncSubmit(forceSending){
  985.     var dcf=D.comForm;
  986.     data="";
  987.     for(var i=1;i<6;i++) if(dcf['data'+i].value.length>0) data+=((i>1)?"&":"")+"data"+i+"="+encodeURIComponent(dcf['data'+i].value);
  988.     return sendData(data,dcf.action,forceSending);
  989. }
  990.  
  991. // Async submit a form
  992. function asyncSubmitForm(formId,forceSending){
  993.     if(!dgi(formId)) return false;
  994.     var frm=dgi(formId);
  995.     var elt;
  996.     data='';
  997.     for(var o=0;o<frm.getElementsByTagName("input").length;o++) {
  998.         elt=frm.getElementsByTagName("input")[o];
  999.         if(elt.name.length){
  1000.             if((elt.type!='radio' && elt.type!='checkbox') || elt.checked){
  1001.                 if(data.length>0) data+='&';
  1002.                 data+=elt.name+'='+encodeURIComponent(elt.value);
  1003.             }
  1004.         }
  1005.     }
  1006.     for(var o=0;o<frm.getElementsByTagName("select").length;o++) {
  1007.         elt=frm.getElementsByTagName("select")[o];
  1008.         if(data.length>0) data+='&';
  1009.         data+=elt.name+'='+encodeURIComponent(elt.value);
  1010.  
  1011.     }
  1012.     return sendData(data,frm.action,forceSending);
  1013. }
  1014.  
  1015.  
  1016.  
  1017.  
  1018.  
  1019.  
  1020.  
  1021.  
  1022.  
  1023.  
  1024.  
  1025.  
  1026. /*********************************************************************************************
  1027.  * wl Object
  1028.  *********************************************************************************************/
  1029. function wJSLib(){
  1030.     var me=this;
  1031.     this.KDS={};
  1032.  
  1033.  
  1034.     /**
  1035.      * Sync Post data without a pre-created form
  1036.      */
  1037.     this.postData = function (data,URL){
  1038.         var f=D.createElement('FORM'), h='';
  1039.         if(data) for(var e in data) h+='<input type="text" name="'+e+'" value="'+data[e]+'">';
  1040.         f.style.display="none";
  1041.         f.enctype="multipart/form-data";
  1042.         f.method="POST";
  1043.         if(URL) f.target=URL;
  1044.         f.innerHTML=h;
  1045.         D.appendChild(f);
  1046.         f.submit();
  1047.     }
  1048.  
  1049.     /**
  1050.      * Go to URL
  1051.      */
  1052.     this.goURL=function(URL){
  1053.         var tURL=D.location.href;
  1054.         // If URL not provided, set current URL (remove hash as it prevents page from reloading)
  1055.         if(!URL){URL=tURL;if(URL.indexOf('#')>0) URL=URL.substr(0,URL.indexOf('#'));}
  1056.         // If only GET parameters passed, reuse current URL
  1057.         else if(URL.substr(0,1)=='?'){
  1058.             if(tURL.indexOf('?')>0) tURL=tURL.substr(0,tURL.indexOf('?'));
  1059.             URL=tURL+URL;
  1060.         }
  1061.         D.location.href=URL;
  1062.     }
  1063.  
  1064.     /**
  1065.      * Pack an associative array into an URL-proof string
  1066.      */
  1067.     this.arrayPack=function(o){
  1068.         if(typeof(o)!='object') return '"'+encodeURIComponent(o)+'"';
  1069.         var s='{',e,nb=0;
  1070.         for(e in o) {
  1071.             s+=((nb++==0)?'':',')+'"'+encodeURIComponent(e)+'"%3A'; // %3A=:
  1072.             if(typeof(o[e])=='object') s+=this.arrayPack(o[e]);
  1073.             else s+='"'+encodeURIComponent(o[e].toString().replace(/\"/g,'\\"'))+'"';
  1074.         }
  1075.         return s+'}';
  1076.     }
  1077.  
  1078.  
  1079.     /**
  1080.      * fade item's opacity to given alpha value
  1081.      * i: item or item's id
  1082.      * a (0-1): target alpha
  1083.      * nbSteps: number of steps to reach target alpha
  1084.      */
  1085.     this.fadeItems={}
  1086.     this.fadeTo = function (i,a,nbSteps){
  1087.         if(typeof(i)=='object'){if(i.id) i=i.id; else i=i.id='id'+Math.floor(999999*Math.random());}
  1088.         if(wl.fadeItems[i]===a) return;
  1089.         var n=dgi(i),ca=n.style.opacity;
  1090.         if(n.style.display=='none'||n.style.visibility=='hidden') ca=0;
  1091.         else if(ca===undefined || ca==='') {
  1092.             if(ca=n.style.filter) {
  1093.                 ca=(ca.substring(ca.indexOf('ty=')+3,ca.indexOf(')')))/100;
  1094.             }
  1095.             else ca=1;
  1096.         }
  1097.         if(nbSteps==undefined) nbSteps=Math.floor(Math.abs(ca-a)*10);
  1098.         wl.fadeItems[i]=a;
  1099.         fade(i,ca*1.0,a*1.0,nbSteps)
  1100.     }
  1101.  
  1102.     /**
  1103.      * Animation function
  1104.      * @param p: animation parameters
  1105.      *            .duration: animation duration, in ms (default 500ms)
  1106.      *            .item: dom node to animate
  1107.      *            or .items: array of {'item':, 'function':} (if .items is passed, .function parameter is only passed in items array)
  1108.      *            .function: animation function, taking as 3 parameters animation step (0-1), animated node, animation data, and returning an associative array of style properties applyed to node.
  1109.      *                 Note: parameters can be passed to animation function by passing extra parameters to this (anim) function
  1110.      *            .callbackStep: function called at every step, passing animation data as parameter
  1111.      *            .callbackComplete: function called when anim completed, passing animation data as parameter
  1112.      *            .reverse: set to true to animate in reverse side
  1113.      */
  1114.     this.anim = function(p){
  1115.         var prop,e,i,it,s;
  1116.         p.time=wl.chrono.microtime();
  1117.  
  1118.         // Init animation
  1119.         if(!p.timeStart) p.timeStart=p.time;
  1120.         p.dt=(p.prevTime!==undefined)?p.time-p.prevTime:0;
  1121.         p.prevTime=p.time;
  1122.         if(!p.duration) p.duration=500;
  1123.         p.step=Math.min(1,(p.time-p.timeStart)/p.duration);
  1124.         if(p.reverse) p.step=1-p.step;
  1125.  
  1126.         // Single item in animation
  1127.         if(p.item) {
  1128.             prop=p['function'](p.step,p)
  1129.             s=p.item.style;
  1130.             for(e in prop) {
  1131.                 if(e=='opacity') setAlpha(p.item,prop[e]); else    s[e]=prop[e];
  1132.             }
  1133.         }
  1134.  
  1135.         // Multiple items in animation
  1136.         if(p.items){
  1137.             for(i=0;i<p.items.length;i++){
  1138.                 it=p.items[i];
  1139.                 s=it.item.style;
  1140.                 prop=it['function'](p.step,it)
  1141.                 for(e in prop) {
  1142.                     if(e=='opacity') setAlpha(it,prop[e]); else    s[e]=prop[e];
  1143.                 }
  1144.             }
  1145.         }
  1146.         // Call animation step callback if set
  1147.         if(p.callbackStep) {if(typeof p.callbackStep=='string') eval(p.callbackStep); else p.callbackStep(p)}
  1148.  
  1149.         // Timeout to next animation step
  1150.         if((p.reverse && p.step>0) || (!p.reverse && p.step<1)) setTimeout(function(){wl.anim(p)},1);
  1151.  
  1152.         // Anim completed
  1153.         else {
  1154.             // Call callback if set
  1155.             if(p.callbackComplete) {if(typeof p.callbackComplete=='string') eval(p.callbackComplete); else p.callbackComplete(p)}
  1156.         }
  1157.     }
  1158.  
  1159.     /**
  1160.      * Common unfold animation profile function
  1161.      * @param p: unfold percentage (0-1)
  1162.      */
  1163.     this.animFunctionUnfold1 = function(p){
  1164.         if(p<0.5) w=Math.min(1,Math.pow(p*2,2)); else w=1-Math.abs(Math.sin(Math.PI*(p-0.5)*2)*Math.exp(-4*p));
  1165.         return w;
  1166.     }
  1167.  
  1168.     /**
  1169.      * Elastic unfold animation profile function
  1170.      * @param p: unfold percentage (0-1)
  1171.      */
  1172.     this.animFunctionUnfold2 = function(p,anim){
  1173.         var i,x=anim.animX,v=anim.animV,dt=2,nx,nb;
  1174.         var m=1,r1=8,r2=10,l=600;
  1175.  
  1176.         // Init speed & position
  1177.         if(x===undefined){
  1178.             v=0; x=1;
  1179.             // Special: windows animation: integrate animation amplitude into elastic computing
  1180.             if(anim.extraParams){
  1181.                 x=Math.abs(anim.extraParams.destW-anim.extraParams.startW)/1000;
  1182.                 if(isNaN(x)) x=1;
  1183.             }
  1184.         }
  1185.  
  1186.         nb=Math.ceil(anim.dt/dt);
  1187.         dt/=1000;
  1188.  
  1189.         // Compute new speed & position
  1190.         if(p==1) x=0;
  1191.         else for(i=0;i<nb;i++){
  1192.             v+=(-x*l-r1*v-r2*v*Math.abs(v))*dt;
  1193.             x+=v*dt
  1194.         }
  1195.  
  1196.         // Store speed & position
  1197.         anim.animX=x;    anim.animV=v;
  1198.  
  1199.         return 1-x;
  1200.     }
  1201.  
  1202.     /**
  1203.      * Common unfold animation profile function (small bounce)
  1204.      * @param p: unfold percentage (0-1)
  1205.      */
  1206.     this.animFunctionFold1 = function(p,anim){
  1207.         if(p<0.5) w=1-Math.min(1,Math.pow(2*p,2)); else w=-0.7*(2*p*p-3*p+1);
  1208.         return w;
  1209.     }
  1210.  
  1211.     /**
  1212.      * Negative exponential unfold animation profile function
  1213.      * @param p: unfold percentage (0->1)
  1214.      */
  1215.     this.animFunctionFold2 = function(p,anim){
  1216.         var f=-9,w=(Math.exp(f*p) - Math.exp(f))/(1-Math.exp(f));
  1217.         if(p==1) w=0;
  1218.         return Math.max(w,0);
  1219.     }
  1220.  
  1221.  
  1222.  
  1223.  
  1224.  
  1225.  
  1226. /**
  1227. * collapse/unfold nodes
  1228. */
  1229.     this.COLLAPSE_DURATION=700; // Time of a fold / unfold animation (ms)
  1230.     this.nodeCollapseInProgress={}; // Assoc. array of collapse animations in progress
  1231.  
  1232.     // Hide / show draggable items contained into collapasable frame
  1233.     this.toggleContainedDragItems = function(item,action){
  1234.         var o,i;
  1235.         if(!W.dd || !dd.elements || !dd.elements.length) return;
  1236.         for(i=0;i<item.childNodes.length;i++){
  1237.             if(item.childNodes[i].attributes && item.childNodes[i].attributes["id"]) {
  1238.                 for(o=0;o<dd.elements.length;o++){
  1239.                     if(dd.elements[o].name==item.childNodes[i].attributes["id"].value) {
  1240.                         if(action=='hide') dd.elements[o].hide(); else dd.elements[o].show();
  1241.                     }
  1242.                 }
  1243.             }
  1244.             if(item.childNodes[i].hasChildNodes) wl.toggleContainedDragItems(item.childNodes[i],action);
  1245.         }
  1246.     }
  1247.  
  1248.     // True if frame is collapsed
  1249.     this.isCollapsed = function(id){
  1250.         var s=dgi(id).style;
  1251.         return (s.display=='none' || s.height=="0px" || s.height=="1px")
  1252.     }
  1253.  
  1254.  
  1255.     /**
  1256.      * Animation function for vertical fold/unfold anims
  1257.      * @param p: anim percentage 0-1
  1258.      * @param n: animated node
  1259.      * @param anim: anim parameters (see wl.anim function). Includes tHeight var indicating block unfolded height
  1260.      */
  1261.     this.nodeCollapseAnim = function(p,anim){
  1262.         var h=Math.floor(anim.tHeight*((anim.reverse)?wl.animFunctionFold1(1-p):wl.animFunctionUnfold1(p,anim)));
  1263.         if(phpBrowser=='ie' && h==0) h=1;// 0px height causes problems under IE
  1264.         return {'height':h+'px'}
  1265.     }
  1266.  
  1267.  
  1268.     /**
  1269.      * Toggle collapse state of a node, and animate
  1270.      * @param id: id of node
  1271.      * @param phpVarName: if set, name of php var that must be async updated to set to true if collapsed, false if unfolded
  1272.      * @param jsCallbackFunction: id of node
  1273.      */
  1274.     this.nodeCollapseToggle = function(id, phpVarName, jsCallbackFunction){
  1275.         if(wl.nodeCollapseInProgress[id]) return;
  1276.         wl.nodeCollapseInProgress[id]=1;
  1277.  
  1278.         if(wl.isCollapsed(id))
  1279.             wl.nodeCollapseUnfold(id, phpVarName, jsCallbackFunction)
  1280.         else
  1281.             wl.nodeCollapseFold(id, phpVarName, jsCallbackFunction)
  1282.     }
  1283.  
  1284.     /**
  1285.      * Unfold a node
  1286.      * See nodeCollapseToggle for parameters
  1287.      */
  1288.     this.nodeCollapseUnfold = function(id, phpVarName, jsCallbackFunction){
  1289.         var s,n,tHeight;
  1290.         if(!(n=dgi(id))) return;
  1291.         s=n.style;
  1292.  
  1293.         // transparently unfold div to compute inner height
  1294.         s.visibility='hidden';s.position='absolute';s.height='';s.display='';
  1295.         tHeight=n.offsetHeight;
  1296.         s.overflow='hidden';s.height='1px';s.position='static';s.visibility='visible';
  1297.  
  1298.         // Anim start callback (backward compatibility)
  1299.         if(jsCallbackFunction && typeof jsCallbackFunction=='string') eval(jsCallbackFunction+'("'+id+'","startUnfold")');
  1300.  
  1301.         // Change toggle button icon
  1302.         if(dgi(id+'BtMinus') && dgi(id+'BtPlus')) {dgi(id+'BtMinus').style.display='inline';dgi(id+'BtPlus').style.display='none';}
  1303.         // Hide / show draggable items contained into collapasable frame
  1304.         wl.toggleContainedDragItems(n,'show');
  1305.  
  1306.         // Update server-side var
  1307.         if(phpVarName) sendData(phpVarName+"=true",PHP_SELF,false);
  1308.  
  1309.         // Start animation
  1310.         wl.anim({'item':n,
  1311.                 'duration':wl.COLLAPSE_DURATION,
  1312.                 'function':wl.nodeCollapseAnim,
  1313.                 'tHeight':tHeight,
  1314.                 'callbackStep':jsCallbackFunction,
  1315.                 'callbackComplete':function(anim){
  1316.                     s=anim.item.style; s.position=''; s.height=''; s.overflow=''; s.margin=''; s.padding='';
  1317.                     if(jsCallbackFunction) eval(jsCallbackFunction+'("'+id+'","doneUnfold")');
  1318.                     if(W.onCollapseFunction) onCollapseFunction(id,"doneUnfold");
  1319.                     if(W.dd) dd.recalc();
  1320.                     wl.nodeCollapseInProgress[id]=0;
  1321.                 }
  1322.             });
  1323.         }
  1324.  
  1325.     /**
  1326.      * Fold a node
  1327.      * See nodeCollapseToggle for parameters
  1328.      */
  1329.     this.nodeCollapseFold = function(id, phpVarName, jsCallbackFunction){
  1330.         var s,n,tHeight;
  1331.         if(!(n=dgi(id))) return;
  1332.         s=n.style;
  1333.  
  1334.         tHeight=n.offsetHeight;
  1335.         s.overflow='hidden';
  1336.  
  1337.         // Anim start callback (backward compatibility)
  1338.         if(jsCallbackFunction && typeof jsCallbackFunction=='string') eval(jsCallbackFunction+'("'+id+'","startFold")');
  1339.  
  1340.         // Change toggle button icon
  1341.         if(dgi(id+'BtMinus') && dgi(id+'BtPlus')) {dgi(id+'BtMinus').style.display='none';    dgi(id+'BtPlus').style.display='inline';}
  1342.  
  1343.         // Update server-side var
  1344.         if(phpVarName) sendData(phpVarName+"=false",PHP_SELF,false);
  1345.  
  1346.         // Start animation
  1347.         wl.anim({'item':dgi(id),
  1348.                 'duration':wl.COLLAPSE_DURATION,
  1349.                 'function':wl.nodeCollapseAnim,
  1350.                 'reverse':1,
  1351.                 'tHeight':tHeight,
  1352.                 'callbackStep':jsCallbackFunction,
  1353.                 'callbackComplete':function(anim){
  1354.                     s=anim.item.style;s.height=((phpBrowser=='ie')?1:0)+'px';s.visibility="hidden";s.margin=0;s.padding=0;
  1355.                     wl.toggleContainedDragItems(dgi(id),'hide');
  1356.                     if(jsCallbackFunction) eval(jsCallbackFunction+'("'+id+'","doneFold")');
  1357.                     if(W.onCollapseFunction) onCollapseFunction(id,"doneFold");
  1358.                     if(W.dd) dd.recalc();
  1359.                     wl.nodeCollapseInProgress[id]=0;
  1360.                 }
  1361.             })
  1362.     }
  1363.  
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.     /**
  1370.     * Scroll divs
  1371.     */
  1372.     function asd(){this.scrolling=0;this.divList=[]}
  1373.     asd.prototype.add = function (item){
  1374.         this.divList.push(item);
  1375.     }
  1376.     asd.prototype.check = function (){
  1377.         if(!dd.obj) return;
  1378.         var it;
  1379.         for(var i=0;i<this.divList.length;i++){
  1380.             it=this.divList[i];
  1381.             if(dd.obj.y>actualOffsetTop(it) && dd.obj.y<actualOffsetTop(it)+2*dd.obj.h && dd.obj.x>actualOffsetLeft(it) && dd.obj.x+dd.obj.w<actualOffsetRight(it)) this.scroll("up",it);
  1382.             if(dd.obj.y>actualOffsetBottom(it)-2*dd.obj.h && dd.obj.y+dd.obj.h<actualOffsetBottom(it) && dd.obj.x>actualOffsetLeft(it) && dd.obj.x+dd.obj.w<actualOffsetRight(it)) this.scroll("down",it);
  1383.         }
  1384.     }
  1385.     asd.prototype.scroll = function (dir,item){
  1386.         if(this.scrolling) return;
  1387.         this.scrolling=1;
  1388.         if(dir=='up') item.scrollTop-=20; else item.scrollTop+=20;
  1389.         W.setTimeout('wl.autoScrollDivs.done()',10);
  1390.     }
  1391.     asd.prototype.done = function (){this.scrolling=0;this.check()}
  1392.  
  1393.     this.autoScrollDivs=new asd();
  1394.  
  1395.     /**
  1396.     * Debug functions
  1397.     */
  1398.     this.dbgw=function(txt,lineBreak){if(parent && parent.winDebug) parent.winDebug(txt,lineBreak); else winDebug(txt,lineBreak)}
  1399.     this.dbgServer=function(txt,toFile){sendData('toFile='+toFile+'&dbgServer='+encodeURIComponent(txt),'/servDbg.php')}
  1400.     //    Chrono
  1401.     function chrono(){this.v=0};
  1402.     chrono.prototype.microtime=function (){return (new Date()).getTime()}
  1403.     chrono.prototype.start=function (){this.chrono=this.microtime()}
  1404.     chrono.prototype.get=function (){return this.microtime()-this.chrono}
  1405.     this.chrono=new chrono();
  1406.  
  1407.     /**
  1408.     * Misc functions
  1409.     */
  1410.  
  1411.     /*
  1412.      * Animations: remove actual processing time to animation timeout value
  1413.      */
  1414.     this.adaptedTimeoutValueStart = function(){this.aTVSC=wl.chrono.microtime()}
  1415.     this.adaptedTimeoutValue = function(t){return Math.max(0,t-wl.chrono.microtime()+this.aTVSC)}
  1416.  
  1417.     // Get flash player from id
  1418.     this.getFlashPlayer = function (id){
  1419.         if(navigator.appName.indexOf("Microsoft") != -1) return window[id]; else return document[id];
  1420.     }
  1421.  
  1422.     /**
  1423.      * Cross-browser (ie. works in IE) setTimeout function
  1424.      */
  1425.     this.setTimeout = function(){
  1426.         var a = arguments;
  1427.         if(a.length<3) return setTimeout(a[0],a[1]);
  1428.         return setTimeout(function(){a[0](a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9])},a[1]);
  1429.     }
  1430.  
  1431.     /**
  1432.      * Cross-browser (ie. works in IE) setTimeout function
  1433.      */
  1434.     this.setInterval = function(){
  1435.         var a = arguments;
  1436.         if(a.length<3) return setInterval(a[0],a[1]);
  1437.         return setInterval(function(){a[0](a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9])},a[1]);
  1438.     }
  1439.     
  1440.     // Add a function calling callback on key pressed, with keycode value as argument, pass null as callback to remove
  1441.     // evt: 'onkeyup' or 'onkeydown'
  1442.     this.setKeycodeListener = function (n,callback,evt){
  1443.         if(typeof n=='string') n=dgi(n);
  1444.         if(!n) return;
  1445.         if(evt='onkeyup'){
  1446.             n.onkeyup=n.onkeydown;
  1447.             n.onkeyup=(callback)?wl.eventToKeycode:null;
  1448.         }
  1449.         else{
  1450.             n.onkeydowntmp=n.onkeydown;
  1451.             n.onkeydown=(callback)?wl.eventToKeycode:null;
  1452.         }
  1453.         n.keycodeListenerCallback=callback;
  1454.     }
  1455.     this.removeKeycodeListener = function (item){
  1456.         item.onkeydown=(item.onkeydowntmp)?item.onkeydowntmp:function(e){};
  1457.     }
  1458.     this.eventToKeycode=function(e){
  1459.         var kc=wl.eventKC(e),srcT,t;
  1460.         if(e){ // Gecko
  1461.             t=e.target
  1462.         }
  1463.         else if(W.event){ // IE & Opera
  1464.             t=W.event.srcElement
  1465.             e=W.event
  1466.         }
  1467.         srcT=t;
  1468.         while(!t.keycodeListenerCallback && t.parentNode && t!=t.parentNode) t=t.parentNode
  1469.         t.keycodeListenerCallback(kc,srcT,e)
  1470.     }
  1471.  
  1472.     // Return keycode from event
  1473.     this.eventKC=function(e){return (e&&e.which)?e.which:(W.event?event.keyCode:0);}
  1474.  
  1475.     // Key Down handler
  1476.     this.KDHandler=function(e){kc=wl.eventKC(e);var t=(e.target)?e.target:e.srcElement;    for(i in wl.KDS[t]) if(i==kc) eval(wl.KDS[t][i])}
  1477.     this.KDHandlerD=function(e){kc=wl.eventKC(e); for(var i in wl.KDS[D]) if(i==kc) eval(wl.KDS[D][i])}
  1478.     this.setKDHandler=function (n,kds){
  1479.         wl.KDS[n]=kds;
  1480.         if(n==D) n.attachEvent?n.attachEvent('onkeydown',wl.KDHandlerD):n.addEventListener('keydown',wl.KDHandlerD,false);
  1481.         else n.attachEvent?n.attachEvent('onkeydown',wl.KDHandler):n.addEventListener('keydown',wl.KDHandler,false);
  1482.     }
  1483.     // Stop event propagation
  1484.     this.stopPropagation=function(event){
  1485.         try{event.stopPropagation()}catch(er){event.cancelBubble = true}
  1486.     }
  1487.     // Prevent backspace key to go back to previous page (instead try goBack function)
  1488.     this.blockBackspace=function(){
  1489.         D.onkeydown=function(e){
  1490.             if(!e) e=W.event;
  1491.             if(wl.eventKC(e)!==8) return true;
  1492.             var t=e.target||e.srcElement;if(t&&t.tagName!='INPUT'&&t.tagName!='TEXTARREA') {
  1493.                 if(W.goBack) setTimeout('goBack()',5);
  1494.                 return false
  1495.             }
  1496.         }
  1497.     }
  1498.  
  1499.  
  1500.     // Add 2 1-level objects, return result
  1501.     this.objectsAdd=function(a,b){
  1502.         for(var e in b) a[e]=b[e];
  1503.         return a;
  1504.     }
  1505.  
  1506.     /**
  1507.     * Buttons (button CSS class, outButton PHP function)
  1508.     */
  1509.     function button(){}
  1510.     this.button=new button();
  1511.  
  1512.     // HTML code for creating a button
  1513.     button.prototype.create = function (caption,script,icon,id,disabled){
  1514.         var iht='<a ';
  1515.         if(id) iht+='id="'+id+'" ';
  1516.         if(caption) iht+='title="'+caption+'" ';
  1517.         if(disabled) iht+='class="buttonDisabled" href="javascript://'+script+'">';
  1518.         else iht+='class="button" href="javascript:'+script+'">';
  1519.         iht+='<i> </i><b>';
  1520.         if(icon) {
  1521.             iht+='<img alt="" src="'+icon+'" onclick="'+((disabled)?'//':'').script+'" ';
  1522.             if(caption && caption.length>0) iht+='style="margin-right:0.4em"';
  1523.             iht+='>';
  1524.         }
  1525.         else
  1526.         iht+='<img alt="" src="/gfx/v.gif">';
  1527.         iht+='<span></span><span>'+caption.replace(/ /g,' ')+'</span></b><u> </u></a>';
  1528.         return iht;
  1529.     }
  1530.     // Is button enabled ?
  1531.     button.prototype.isEnabled = function (bt){
  1532.         if(typeof bt=='string') bt=dgi(bt);
  1533.         if(!bt) return false;
  1534.         return bt.className=='button'
  1535.     }
  1536.  
  1537.     // Enable button
  1538.     button.prototype.enable = function (bt,en){
  1539.         if(en===false) return wl.button.disable(bt);
  1540.  
  1541.         if(typeof bt=='string') bt=dgi(bt);
  1542.         if(!bt || bt.className=='button') return;
  1543.         bt.className='button';
  1544.         var hr=bt.getAttribute("href");
  1545.         if(hr.substr(11,3)=='//#') bt.href=hr.substr(14); // if href is like javascript://#, turn it into an URL
  1546.         else bt.href='javascript:'+hr.substr(13);// if href is like javascript://, turn it into a javascript action
  1547.         var img=bt.firstChild.nextSibling.firstChild;
  1548.         // remove // from onclick property
  1549.         if(img.hasAttribute && img.hasAttribute("onclick")){txt=img.getAttribute("onclick")+'';img.onclick=txt.substr(2);}
  1550.         else if(img.onclick) {img.onclick=function (){eval(img.parentNode.parentNode.href.replace(/\/\//,'')) }} // IE
  1551.     }
  1552.  
  1553.     // Disable button
  1554.     button.prototype.disable = function (bt){
  1555.         if(typeof bt=='string') bt=dgi(bt);
  1556.         if(!bt || bt.className=='buttonDisabled') return;
  1557.         bt.className='buttonDisabled';
  1558.         var hr=bt.href;
  1559.         if(hr.substr(0,11)=='javascript:') bt.href='javascript://'+hr.substr(11);
  1560.         else bt.href='javascript://#'+hr;
  1561.         var img=bt.firstChild.nextSibling.firstChild;
  1562.         if(img.onclick) img.onclick='//'+img.onclick;
  1563.  
  1564.         if(img.hasAttribute){if(img.hasAttribute("onclick")) {img.onclick='//'+img.getAttribute("onclick")}}
  1565.         else if(img.onclick) img.onclick='//'+img.onclick;
  1566.     }
  1567.  
  1568.     // Set icon
  1569.     button.prototype.setIcon = function (bt,nSrc){
  1570.         if(typeof bt=='string') bt=dgi(bt);
  1571.         if(!bt) return;
  1572.         var img=bt.firstChild.nextSibling.firstChild;
  1573.         if(img.tagName=='IMG') img.src=nSrc;
  1574.         else img.style.filter=img.style.filter.substr(0,img.style.filter.indexOf("src='")+5)+nSrc+"')";
  1575.     }
  1576.  
  1577.     // Set caption/label
  1578.     button.prototype.setCaption = function (bt,txt){
  1579.         if(typeof bt=='string') bt=dgi(bt);
  1580.         if(!bt) return;
  1581.         if(bt.firstChild.nextSibling.firstChild.nextSibling.nextSibling)
  1582.             bt.firstChild.nextSibling.firstChild.nextSibling.nextSibling.innerHTML=txt;
  1583.         else
  1584.             bt.firstChild.nextSibling.firstChild.nextSibling.innerHTML=txt;
  1585.     }
  1586.  
  1587.     // Set function
  1588.     button.prototype.setFunction= function (bt,funcTxt){
  1589.         if(typeof bt=='string') bt=dgi(bt);    if(!bt) return;
  1590.         if(bt.className=='button'){
  1591.             bt.href='javascript:'+funcTxt;
  1592.             var img=bt.firstChild.nextSibling.firstChild;
  1593.             if(img) img.onclick=function(){eval(funcTxt)}
  1594.         }
  1595.     }
  1596.  
  1597.     /**
  1598.     * Block items functions
  1599.     */
  1600.     function bI (id){if(typeof id == 'string') this.n=dgi(id); else this.n=id;}
  1601.     bI.prototype.enable=function(doEnable){if(doEnable || doEnable==undefined) $(this.n).e.className().remove('biDisabled'); else $(this.n).e.className().add('biDisabled')}
  1602.     bI.prototype.over=function(){if(this.n.className.indexOf("biDisabled")==-1) $(this.n).e.className().add('biOver')}
  1603.     bI.prototype.out=function(){$(this.n).e.className().remove('biOver')}
  1604.     bI.prototype.select=function(doSelect,check){
  1605.         var na,e;
  1606.         if($(this.n).e.className().has('biDisabled')) return;
  1607.         if(doSelect||doSelect==undefined) {
  1608.             // Set item as selected (or remove selection if already selected & checkbox
  1609.             if(check && $(this.n).e.className().has('biSel')) $(this.n).e.className().remove('biSel'); else $(this.n).e.className().add('biSel');
  1610.             // unselect other blockitems
  1611.             if((na=this.n.getAttribute('name')) && !check) {
  1612.                 var items=D.getElementsByTagName('FIELDSET');
  1613.                 for(e in items) if(items[e] && items[e].getAttribute && items[e].getAttribute('name')==na && items[e]!=this.n) wl.blockItem(items[e]).select(0);
  1614.             }
  1615.         }
  1616.         else $(this.n).e.className().remove('biSel')
  1617.     }
  1618.     bI.prototype.selected=function(){return this.n.className.indexOf("biSel")!=-1}
  1619.     bI.prototype.enabled=function(){return this.n.className.indexOf("biDisabled")==-1}
  1620.     this.blockItem=function(id){return new bI(id)}
  1621.  
  1622.     // Block items group
  1623.     function bIG(name){this.n=name}
  1624.     bIG.prototype.getItems=function(){
  1625.         var r=[],l=D.getElementsByTagName('FIELDSET');
  1626.         for(e in l) if(l[e] && l[e].getAttribute && l[e].getAttribute('name')==this.n) r.push(new wl.blockItem(l[e]));
  1627.         return r;
  1628.     }
  1629.     // Return an array of id of selected item(s)
  1630.     bIG.prototype.getSelectedItemsIds=function(){
  1631.         var s=Array(),items=D.getElementsByTagName('FIELDSET'),e,i=0;
  1632.         for(e in items) if(items[e] && items[e].getAttribute && items[e].getAttribute('name')==this.n && wl.blockItem(items[e]).selected()) s[i++]=items[e].id;
  1633.         return s;
  1634.     }
  1635.     this.blockItemGroup=function(name){return new bIG(name)}
  1636.  
  1637.  
  1638.     /**
  1639.     * UI communication
  1640.     * Send command to UI
  1641.     * If returnDataName set, fill result into input named so, and fire onkeyup event
  1642.     * Else if callback set, call callback function with return value
  1643.     */
  1644.     this.UICommandCallbackF=0;
  1645.     this.UICommandCallbackN=0;
  1646.     this.UICommandCallback = function (e){
  1647.         if((typeof wl.UICommandCallbackF)=='string') eval(wl.UICommandCallbackF+'(wl.UICommandCallbackN.value)');
  1648.         else wl.UICommandCallbackF(wl.UICommandCallbackN.value);
  1649.     }
  1650.     this.UICommand=function (command, returnDataName, callback){
  1651.         var n;
  1652.         if(callback && !returnDataName){
  1653.             n=dgi("uicommandcb")
  1654.             if(!n){
  1655.                 n=D.createElement('INPUT');
  1656.                 n.id='uicommandcb';
  1657.                 n.name='uicommandcb';
  1658.                 returnDataName='uicommandcb';
  1659.                 with(n.style){position='absolute';top=0;display='none';}
  1660.                 D.body.appendChild(n);
  1661.             }
  1662.             wl.UICommandCallbackF=callback
  1663.             wl.UICommandCallbackN=n
  1664.             n.onkeyup=this.UICommandCallback
  1665.             returnDataName='uicommandcb';
  1666.         }
  1667.         top.location.href="UI:"+command+((returnDataName)?':'+returnDataName:'');
  1668.     }
  1669.     // Open a web popup in application, and callback cb function (or function name) with return string
  1670.     this.UIWebPopup=function(url,cb){
  1671.         wl.UICommand('webPopup:'+url,false,cb);
  1672.     }
  1673.     // web popup response return
  1674.     this.UIWebPopupReturn=function(data){
  1675.         if(isApp) wl.UICommand('close:'+data);
  1676.     }
  1677.     // Set response of UI web popup when closed by user with esc or window closed
  1678.     this.UIWebPopupSetCancelReturnArgs=function(r){
  1679.         wl.UICommand('setCancelReturnArgs:'+r);
  1680.     }
  1681.  
  1682.  
  1683.     /**
  1684.      * Show help
  1685.      */
  1686.     this.showHelp=function(capt){
  1687.         var a=W,b=W;while(a.parent && a!=a.parent) {
  1688.             a=a.parent;
  1689.             try{if(a.dd) b=a} catch(e){break;}
  1690.         }
  1691.         b.sendData('hId='+capt,'/help.php');
  1692.     }
  1693.  
  1694.     // Copy text to clipboard (IE)
  1695.     this.clipboardCopy=function(id){
  1696.         with(dgi(id).createTextRange()){
  1697.             execCommand("RemoveFormat");
  1698.             execCommand("Copy");
  1699.         }
  1700.     }
  1701.  
  1702.  
  1703.  
  1704.     /**
  1705.     * Fade any CSS p from current to "end" state
  1706.     * @param id: id of node
  1707.     * @param p: style property to fade
  1708.     * @param end: final state (no unit set, use current state's)
  1709.     * @param type: 'linear' or 'exponential'  (opt:linear)
  1710.     * @param nbSteps: 'linear' or 'exponential' (opt:imgFadeSteps)
  1711.     * @param cb: callback on completition (opt:no)
  1712.     */
  1713.     this.fadeStyle = function (id, p, end, type, nbSteps, cb){
  1714.         var isStyle=(p!='scrollTop'&&p!='scrollLeft');
  1715.  
  1716.         var n=dgi(id),s=(isStyle)?n.style:n;val=''+s[p],unit='',v=0;
  1717.         if(val==''){
  1718.             if(p=='height') val=''+n.offsetHeight+'px';
  1719.             if(p=='width') val=''+n.offsetWidth+'px';
  1720.         }
  1721.  
  1722.         if(val.substr(val.length-1)=='%') unit='%';
  1723.         if(val.substr(val.length-2)=='px') unit='px';
  1724.         v=1*val.substr(0,val.length-unit.length);
  1725.  
  1726.         // Set number of steps
  1727.         if(nbSteps==undefined) {if(v==end) nbSteps=1; else nbSteps=10;}
  1728.         if(nbSteps<=1) v=end;
  1729.         else {if(type=='exponential') v=(2*v+end)/3; else    v+=(end*1-v*1)/nbSteps;}
  1730.  
  1731.         if(p=='alpha') setAlpha(n,v);
  1732.         else {
  1733.             if(Math.floor(v)==0 && (p=='height'||p=='width')) s.display='none'; // IE WA: height/width 0px doesn't work
  1734.             else s[p]=''+Math.floor(v)+unit;
  1735.         }
  1736.  
  1737.         if(nbSteps<=1){if(cb && cb!=='undefined') eval(cb); return;}
  1738.         W.setTimeout('wl.fadeStyle("'+id+'", "'+p+'", '+end+', "'+type+'", '+(nbSteps-1)+', "'+cb+'")',((phpBrowser=='gecko')?50:5));
  1739.     }
  1740.  
  1741.     /**
  1742.      * ext/img functions
  1743.      */
  1744.     this.extImageSrc=function (filename,w,h,opt){
  1745.         if(!opt) opt={};
  1746.         return '/img/w.'+w+'/h.'+h+'/cache.'+((opt['noCache'])?0:1)+'/resId.'+resId+'/file.'+encodeURIComponent(filename).replace(/%2F/g,"/");
  1747.     }
  1748.  
  1749.     /**
  1750.      * Preload an image into browser cache
  1751.      * @param src: image src
  1752.      * @param src: onloadCallback: function called on image load
  1753.      */
  1754.     this.imgPreload=function(src,onloadCallback,onerrorCallback){
  1755.         var i=new Image()
  1756.         if(onloadCallback) i.onload=onloadCallback;
  1757.         if(onerrorCallback) i.onerror=onerrorCallback;
  1758.         i.src=src;
  1759.     }
  1760.  
  1761.     /**
  1762.      * Asynchronous requests
  1763.      */
  1764.     this.AsynchronousRequest = function (){
  1765.         this.seq=1; // Sequential number of requests
  1766.         this.reqs={}; // Array of id=>requests
  1767.         this.method='POST'; // Default requests method (allways GET, may be set tp POST);
  1768.  
  1769.         /**
  1770.          * Main async request function
  1771.          * d: data, url encoded or associative array
  1772.          * url: target URL, current if not set
  1773.          * mode: 0=immediate, 1=queue if other requests in progress
  1774.          * Return: request id, or 0 if failure
  1775.          */
  1776.         this.send = function (d,url,mode){
  1777.             var r,dd='';
  1778.             if(d.fileSize) this.method = 'FILE';
  1779.             // If data is a file,don't do anything now
  1780.             if(d.fileSize){
  1781.                 dd=d;
  1782.             }
  1783.             // Convert args array to URL encoded format
  1784.             else {
  1785.                 if(typeof(d)=='object'){for(e in d) dd+='&'+e+'='+encodeURIComponent(d[e])} else dd=d;
  1786.                 dd=dd.replace(/\+/g,"$weezoPlus$")+"&asyncRequest=1"+((W.resId)?"&resId="+resId:"");
  1787.                 if(dd.substr(0,1)=='&') dd=dd.substr(1);
  1788.             }
  1789.  
  1790.             // Fill URL
  1791.             if(!url) url=D.location.href;
  1792.             // Set mode
  1793.             if(mode!=1) mode=0;
  1794.             // Create request
  1795.             if(!(r=new this.request(dd,url,mode))) return 0;
  1796.             // Store in requests array
  1797.             wl.asr.reqs[r.id]=r;
  1798.             // Send or let in queue
  1799.             if(!mode || count(wl.asr.reqs)==1) r.send();
  1800.             return r.id;
  1801.         }
  1802.  
  1803.         /**
  1804.          * Cancel all requests
  1805.          */
  1806.         this.cancelAll = function (){
  1807.             var limit=0;
  1808.             while(count(wl.asr.reqs) && limit++<5) for(e in wl.asr.reqs) {
  1809.                 if(wl.asr.reqs[e] && wl.asr.reqs[e].state==2) try{wl.asr.reqs[e].abort()} catch(e){}
  1810.                 delete(wl.asr.reqs[e])
  1811.             };
  1812.         }
  1813.  
  1814.         /**
  1815.          * Cancel single request (also called on request completed)
  1816.          * req: request or request id
  1817.          */
  1818.         this.cancel = function (req){
  1819.             var id;
  1820.             if(typeof req!='object') id=req; else id=req.id;
  1821.             if(wl.asr.reqs[id]){
  1822.                 // Stop if still in progress
  1823.                 if(wl.asr.reqs[id].state==2) try{wl.asr.reqs[id].abort()} catch(e){}
  1824.                 // Remove from list
  1825.                 try{delete(wl.asr.reqs[id])} catch(e){}
  1826.             }
  1827.             // Launch next pending request
  1828.             for(var e in wl.asr.reqs) if(wl.asr.reqs[e].state==1) return wl.asr.reqs[e].send();
  1829.         }
  1830.  
  1831.         /**
  1832.          * Return request item from id
  1833.          */
  1834.         this.getRequest = function (id){return wl.asr.reqs[id];}
  1835.  
  1836.         /**
  1837.          * Request object. See .send() for args (except d must be url-encoded)
  1838.          */
  1839.         this.request = function (d,url,mode){
  1840.             var rid=wl.asr.seq++;
  1841.             this.data=d; // Request data (url-encoded query string)
  1842.             this.url=url;
  1843.             this.id=rid; // Request id, index of ASR.reqs array
  1844.             this.state=mode; // Request state (0, pending, 1 in queue, 2 in progress, 3 completed (process in progress)
  1845.             this.RTReadBytes=0;
  1846.             this.RTProcessed=0;
  1847.             this.method='GET';
  1848.  
  1849.             // Detect data is a file => switch to file upload mode
  1850.             if(d.fileSize) this.method = 'FILE';
  1851.  
  1852.             // All browsers except IE6-
  1853.             if(W.XMLHttpRequest) this.xhr = new XMLHttpRequest();
  1854.             // IE6- or IE7+ with disabled native XMLHTTP request
  1855.             else if (W.ActiveXObject) {
  1856.                 try{this.xhr = new ActiveXObject("MSXML2.XMLHTTP.6.0")}
  1857.                 catch(e){
  1858.                     try{this.xhr = new ActiveXObject("Microsoft.XMLHTTP");}
  1859.                     catch(e){alert('XMLHttpRequest error: Internet Explorer asynchronous request and ActiveX disabled');return false}
  1860.                 }
  1861.             }
  1862.             try{this.xhr.id=rid}catch(e){} // Also store id in XMLHttpRequest object
  1863.  
  1864.             /**
  1865.              * Do send data
  1866.              */
  1867.             this.send=function(async){
  1868.                 if(async==undefined) async=true;
  1869.                 // GET request (only if query string not too long)
  1870.                 if(wl.asr.method=="GET" && d.length<1950) {
  1871.                     // Open
  1872.                     if(url.indexOf('?')!=-1) this.xhr.open("GET", url+'&'+d,async); else this.xhr.open("GET", url+'?'+d, async);
  1873.                     this.method='GET';
  1874.                     // Send
  1875.                     this.xhr.send(null);
  1876.                 }
  1877.                 // POST / FILE request
  1878.                 else {
  1879.                     // Open
  1880.                     this.xhr.open("POST", this.url, async);
  1881.                     // Set headers
  1882.                     if(wl.asr.method=='POST')
  1883.                         this.xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
  1884.                     // file upload
  1885.                     else{
  1886.                         this.xhr.setRequestHeader('Content-Type', 'multipart/form-data');
  1887.                         this.xhr.setRequestHeader('X-File-Name', this.data.fileName);
  1888.                         this.xhr.setRequestHeader('X-File-Size', this.data.fileSize);
  1889.                     }
  1890.                     // Send
  1891.                     this.xhr.send(this.data);
  1892.                 }
  1893.                 this.state=2; // Set in progress
  1894.                 this.data=''; // Clear request args as they are not needed any longer
  1895.  
  1896.                 // Show request in progress
  1897.                 wl.asr.setRequestIndicator(1)
  1898.  
  1899.                 // Opera WA: use timer to monitor reception
  1900.                 if(phpBrowser=='opera') {
  1901.                     this.RTInt=W.setTimeout(this.xhr.onreadystatechange,100,this.id);
  1902.                     this.TO=1;
  1903.                 }
  1904.             }
  1905.  
  1906.  
  1907.             // Set callback
  1908.             this.xhr.onreadystatechange = function (id) {
  1909.                 // Callback seems sometimes to be called after window is called, throwing an error on wl
  1910.                 if(!window.wl) return;
  1911.                 // this is xhr (FF)
  1912.                 if(this && this.id) rid=this.id;
  1913.                 // Called by timer (opera RT WA)
  1914.                 else if(id && typeof(id)!='object') rid=id;
  1915.  
  1916.                 // Retreive request
  1917.                 var r,xhr,rt;
  1918.                 r=wl.asr.reqs[rid];
  1919.  
  1920.                 if(!r||!r.xhr) return; // Not in list anymore => canceled request
  1921.                 xhr=r.xhr;
  1922.  
  1923.                 if(r.TO) r.RTInt=W.setTimeout(r.xhr.onreadystatechange,100,id); // Restart timeout
  1924.  
  1925.                 try{rt=xhr.responseText} catch(e){return} // IE Workaround on uncompleted requests
  1926.  
  1927.                 // Real-time processing
  1928.                 var rl=rt.length,s,e,c,geckoBuffer='';
  1929.  
  1930.                 if(rl==r.RTReadBytes && xhr.readyState!=4) return;
  1931.                 r.RTReadBytes=rl;
  1932.                 while((e=rt.indexOf('</JSRT>',r.RTProcessed))>r.RTProcessed){
  1933.                     s=rt.indexOf('<JSRT>',r.RTProcessed); c=rt.substring(s+6,e).replace(/</g,'<');
  1934.                     // Process extracted js code
  1935.                     if(W.PHPDebug) {try{eval(c)} catch(e){alert('RT Async err: '+e+"\n"+c)}} else eval(c);
  1936.                     r.RTProcessed=e+7;
  1937.                 }
  1938.                 if(xhr.readyState!=4) return;
  1939.  
  1940.                 // Request completed: process
  1941.                 wl.asr.setRequestIndicator(0);
  1942.                 r.state=3;
  1943.  
  1944.                 // Failed request
  1945.                 if(xhr.status!=200 || !xhr.responseText.length) return r.cancel();
  1946.  
  1947.                 // Process response
  1948.                 var xmlRoot,act,c,n,ns,add,attr,o,i;
  1949.                 if(!xhr.responseXML || (xmlRoot=xhr.responseXML.documentElement)==null){
  1950.                     if(W.PHPDebug) alert('XML error: '+xhr.responseText);return r.cancel();
  1951.                 }
  1952.  
  1953.                 // Browse XML response nodes
  1954.                 for(i=0;i<xmlRoot.childNodes.length;i++) if((n=xmlRoot.childNodes[i]).nodeType==1){
  1955.                     if(n.firstChild) c=xmlRoot.childNodes[i].firstChild.nodeValue; else c='';
  1956.                     act=n.nodeName;
  1957.                     // Execute javascript
  1958.                     if(act=="JSAction") {
  1959.                         var c=(n.getAttribute('commitBuffer'))?geckoBuffer:c;
  1960.                         if(W.PHPDebug) {try{eval(c)} catch(e){alert('Async err: '+e+"\n"+c)}} else eval(c);
  1961.                     }
  1962.                     // Change node(s) innerHTML
  1963.                     if(act=="innerHTML"){
  1964.                         if(n.getAttribute('add')) add=true; else add=false;
  1965.                         ns=Array();
  1966.                         if(attr=n.getAttribute('nodeId')) ns[0]=dgi(attr);
  1967.                         else if(attr=n.getAttribute('nodeName')) ns=D.getElementsByName(attr);
  1968.                         else if(attr=n.getAttribute('nodeTagName')) ns=D.getElementsByTagName(attr);
  1969.                         for(o=0;o<ns.length;o++) if(ns[o]){
  1970.                             if(add) ns[o].innerHTML+=((n.getAttribute('commitBuffer'))?geckoBuffer:c);
  1971.                             else ns[o].innerHTML=((n.getAttribute('commitBuffer'))?geckoBuffer:c);
  1972.                         }
  1973.                     }
  1974.                     // Add data to gecko buffer
  1975.                     if(act=="addToBuffer") geckoBuffer+=c;
  1976.  
  1977.                     // Clear buffer
  1978.                     if(n.getAttribute('commitBuffer')) geckoBuffer='';
  1979.                 }
  1980.  
  1981.                 // Remove request from list, proceed to next in queue
  1982.                 r.cancel();
  1983.             }
  1984.  
  1985.  
  1986.             /**
  1987.              * Cancel request function
  1988.              */
  1989.             this.cancel=function(){wl.asr.cancel(this.id)}
  1990.  
  1991.             return this.id;
  1992.         }
  1993.  
  1994.         // Set request-in-progress indicator
  1995.         this.setRequestIndicator = function (st){
  1996.             if(dgi('asyncRequestIndicator')) dgi('asyncRequestIndicator').style.display=(st)?'':'none';
  1997.             else if(W.asyncRequestIndicator) asyncRequestIndicator(st);
  1998.             else if(W.winMe) winMe.asyncRequestIndicator(st);
  1999.         }
  2000.     }
  2001.  
  2002.     this.asr=new this.AsynchronousRequest();
  2003. }
  2004.  
  2005. var wl=new wJSLib();
  2006.  
  2007. // Legacy sendData function
  2008. function sendData(d,URL,force){return wl.asr.send(d,URL,0);}
  2009.  
  2010.  
  2011.  
  2012. /*********************************************************************************************
  2013.  * Extended DOM node Object
  2014.  *********************************************************************************************/
  2015.  
  2016. function $(node){
  2017.     if(typeof node=='string') node=D.getElementById(node);
  2018.     node.e=new wlNode(node);
  2019.     return node;
  2020. }
  2021. function wlNode(node){this.n=node}
  2022.  
  2023. // Remove DOM node
  2024. wlNode.prototype.remove=function(){if((n=this.n) && n.parentNode) n.parentNode.removeChild(n)}
  2025.  
  2026. // Get actual style value, from style or css
  2027. wlNode.prototype.getStyle=function(styleProp){
  2028.     if(!(n=this.n)) return;
  2029.     if (n.currentStyle) return n.currentStyle[styleProp];
  2030.     else if (W.getComputedStyle) return D.defaultView.getComputedStyle(n,null).getPropertyValue(styleProp);
  2031. }
  2032.  
  2033. // Set transparency (0<alpha<1)
  2034. wlNode.prototype.setAlpha=function(alpha){setAlpha(this.n,alpha)}
  2035.  
  2036. // offsets from top-left corner of document
  2037. wlNode.prototype.actualOffsetLeft=function(){return actualOffsetLeft(this.n)}
  2038. wlNode.prototype.actualOffsetRight=function(){return actualOffsetRight(this.n)}
  2039. wlNode.prototype.actualOffsetTop=function(){return actualOffsetTop(this.n)}
  2040. wlNode.prototype.actualOffsetBottom=function(){return actualOffsetBottom(this.n)}
  2041.  
  2042. // Center item on page
  2043. // Optional: offX & offY: offset (used to tweak position)
  2044. wlNode.prototype.center=function(offX,offY){
  2045.     var w,h,l,t,n=this.n;
  2046.     if(W.winMe){w=winMe.getInnerWidth();h=winMe.getInnerHeight()} else if(W.dd){w=dd.getWndW();h=dd.getWndH()}
  2047.     l=(w-n.offsetWidth )/2+((W.pageXOffset)?W.pageXOffset:D.body.scrollLeft)+((offX)?offX:0);
  2048.     t=(h-n.offsetHeight)/2+((W.pageYOffset)?W.pageYOffset:D.body.scrollTop)+((offY)?offY:0);
  2049.     if(W.dd && n.id && dd.elements[n.id]) dd.elements[n.id].moveTo(l,t);
  2050.     else with(n.style){left=l;top=t;}
  2051. }
  2052.  
  2053.  
  2054. // Extended DOM node class functions
  2055. wlNode.prototype.className=function(){return new wlNodeClass(this.n)}
  2056. wlNodeClass=function(node){this.n=node}
  2057. // Add a class to node
  2058. wlNodeClass.prototype.add=function(cl){
  2059.     if(!(n=this.n)) return; // No node
  2060.     if(!n.className) return n.className=cl; // Node has no class
  2061.     if(n.className.indexOf(cl)!=-1) return; // Node already has class
  2062.     n.className=n.className?n.className+' '+cl:cl;
  2063. }
  2064. // Remove a class from node
  2065. wlNodeClass.prototype.remove=function(cl){
  2066.     if(!(n=this.n) || !n.className) return; // No node or no class
  2067.     n.className=n.className.replace(new RegExp("[ ]{0,1}"+cl),"")
  2068. }
  2069. // Check if node has a class
  2070. wlNodeClass.prototype.has=function(cl){return (this.n && this.n.className)?(this.n.className.indexOf(cl)!=-1):0}
  2071.  
  2072.  
  2073.  
  2074.  
  2075.  
  2076.  
  2077.  
  2078. // Script load monitoring
  2079. if(W.lFunc) lFunc('common',50);